EN ESTA SECCIÓN
En el corazón de la economía global existe una paradoja fundamental: mientras que algunos indicadores sugieren una relación lineal y predecible entre el desarrollo económico y el bienestar social, la realidad es mucho más compleja y matizada. Tomemos un ejemplo: Costa Rica tiene una esperanza de vida comparable a la de países europeos desarrollados, pero con un PIB per cápita significativamente menor; Qatar, por su parte, lidera en PIB per cápita pero no encabeza necesariamente en todos los indicadores de bienestar social (Shkolnikov et al., 2019). Estas “anomalías” no son excepciones sino revelaciones de una verdad fundamental: el desarrollo no es unidimensional.
El problema central que motiva este trabajo es fundamental: ¿Cuáles son realmente los “tipos” de desarrollo que caracterizan la economía mundial cuando se analiza simultáneamente un conjunto amplio de 17 indicadores económicos, sociales, tecnológicos y ambientales? No se trata de responder cuál país es más “rico”, sino algo más profundo: descubrir si existen estructuras ocultas en los datos que agrupen países con perfiles similares más allá de la geografía o las clasificaciones convencionales. Específicamente, la pregunta es: ¿Colombia y Uruguay podrían compartir más similitudes con algunos países asiáticos que con sus propios vecinos latinoamericanos? ¿Existe realmente un “grupo de países con baja renta pero alto acceso tecnológico”? ¿Las características ambientales y demográficas se alinean con la riqueza económica o presentan patrones independientes?
Históricamente, el desarrollo internacional se ha medido mediante indicadores aislados. El PIB per cápita domina los rankings; la esperanza de vida se analiza independientemente; la conectividad digital se observa separadamente. Este enfoque fragmentado es problemático porque el desarrollo no es unidimensional: un país puede ser económicamente exitoso pero frágil en salud pública, o tener excelente conectividad digital pero vulnerabilidad ambiental crítica (Jolliffe, 2002; World Bank, 2023). Los datos del año 2022 capturan un momento único en la historia económica global: post-pandemia de COVID-19, con efectos heterogéneos según país. Algunos recuperaron rápidamente su dinamismo; otros enfrentaron cicatrices estructurales persistentes en empleo, salud y finanzas públicas (World Bank, 2023).
El Banco Mundial proporciona 17 indicadores reconocidos internacionalmente que miden dimensiones distintas: factores económicos (PIB per cápita, crecimiento del PIB, inversión extranjera, remesas, industria, comercio), indicadores de salud y bienestar (esperanza de vida, mortalidad infantil, gasto en salud), variables de conectividad tecnológica (acceso a electricidad, uso de internet, suscripciones móviles) y aspectos ambientales y demográficos (área boscosa, tierra cultivable, crecimiento poblacional) (World Bank, 2023). Analizar estas 17 variables de forma independiente genera ruido; analizarlas de manera integrada puede revelar patrones coherentes que informan políticas públicas, estrategias de cooperación internacional y decisiones de inversión.
El desafío es modelar una pregunta sin respuesta predefinida: ¿Qué agrupamientos naturales de países emergen cuando se analiza simultáneamente esta multiplicidad de indicadores? Este es precisamente el rol del aprendizaje no supervisado—un conjunto de técnicas que descubren patrones en datos sin etiquetas previas, sin clasificaciones arbitrarias impuestas externamente (Charrad et al., 2014; Jolliffe, 2002).
Lo que sigue es una cartografía multidimensional de la economía global en el contexto post-pandemia: no solo se responde “¿en qué grupos se dividen los países?”, sino, más profundamente, “¿qué revelan estos grupos sobre mecanismos reales del desarrollo, oportunidades compartidas, restricciones comunes y trayectorias viables para diferentes sociedades?” Los resultados no serán una clasificación administrativa sino un descubrimiento empírico basado en lo que los datos de 180 países en 2022 efectivamente revelan.
La base de datos utilizada en este análisis proviene de la compilación World Development Indicators (WDI) del Banco Mundial, considerada la principal fuente internacional de estadísticas comparables sobre desarrollo económico y social (World Bank, 2023). Los WDI representan el esfuerzo más comprehensivo del Banco Mundial para consolidar indicadores de desarrollo de fuentes oficialmente reconocidas, incluyendo oficinas nacionales de estadística, bancos centrales, agencias de las Naciones Unidas, instituciones de investigación y contribuyentes del sector privado (World Bank, 2023; Jeanty, 2010).
La base WDI contiene aproximadamente 1,600 indicadores de series temporales para 217 economías y más de 40 grupos de países, con datos para muchos indicadores que se remontan más de 50 años (World Bank, 2023). Los datos son compilados mediante metodologías estandarizadas que garantizan comparabilidad internacional, transparencia metodológica y robustez estadística (World Bank, 2019). El proceso de selección de indicadores del WDI sigue cuatro criterios fundamentales: facilidad de uso (accesibilidad y claridad para usuarios diversos), confiabilidad (reputación y credibilidad de la fuente), cobertura (amplitud geográfica y temporal), y calidad (rigor metodológico y precisión) (Behar & Mok, 2024).
Para este análisis, se filtro información exclusivamente para países individuales (eliminando bloques regionales o agrupaciones económicas) del año 2022. El dataset resultante contiene aproximadamente 180-200 países, según la disponibilidad de datos completos, donde cada observación representa una unidad soberana comparable en un único punto temporal.
El año 2022 marca un punto de inflexión crítico en la economía global, representa el momento post-pandemia en que las trayectorias de recuperación de cada país se hacen visibles y diferenciadas. Mientras algunos países desarrollados con capacidad fiscal recuperaron o superaron niveles pre-COVID-19, economías emergentes enfrentaban cicatrices estructurales persistentes en empleo, inflación descontrolada, y aumento de deuda pública (Banco Mundial, 2022; FMI, 2023; CEPAL, 2023). La desigualdad global se amplió drásticamente: el crecimiento proyectado para América Latina en 2022 era apenas 2.6%, mientras la desigualdad de ingresos aumentó significativamente después de dos décadas de mejoras (BID, 2022).
En este contexto, 2022 funciona como un “revelador” excepcional de vulnerabilidades y fortalezas estructurales subyacentes de los países: aquellos con sistemas de salud robustos, infraestructura tecnológica consolidada y economías diversificadas mostraron resiliencia; los que enfrentaban fragilidades estructurales experimentaron impactos persistentes (Banco Mundial, 2022; CIDOB, 2022). Por tanto, 2022 es un año extraordinariamente informativo para identificar perfiles reales de desarrollo, ya que las diferencias entre países se magnificaron visiblemente, permitiendo observar no clasificaciones arbitrarias sino estructuras auténticas de capacidad nacional.
Los datos utilizados provienen del World Development Indicators del Banco Mundial.
El dataset construido para este análisis integra 17 variables cuantitativas que capturan las múltiples dimensiones del desarrollo contemporáneo. Estas variables se organizan en cinco áreas temáticas que, en conjunto, ofrecen una perspectiva comprehensiva del desempeño socioeconómico, tecnológico y ambiental de cada país. A continuación, se presenta una descripción detallada de cada variable según su área temática.
La inclusión de variables económicas es fundamental porque el desarrollo ha sido históricamente conceptualizado como un proceso de transformación estructural impulsado por el crecimiento económico (World Bank, 2023; Piketty, 2022). Sin embargo, el crecimiento económico no es unidimensional: requiere tanto un nivel absoluto de riqueza (PIB per cápita) como dinamismo y expansión (crecimiento del PIB), diversificación productiva (industria), y capacidad de atracción de inversión internacional (IED) que transfiera conocimiento y capital (ECB, 2018). Además, las economías contemporáneas están integradas globalmente, por lo que exportaciones, importaciones y remesas son transmisores clave de oportunidades y vulnerabilidades económicas (World Bank, 2023)., en la tabla 1 las observamos.
variables_economicas <- data.frame(
Variable = c(
"PIB per cápita (US$)",
"Crecimiento del PIB (% anual)",
"Inversión extranjera directa (% PIB)",
"Remesas recibidas (% PIB)",
"Industria (% PIB)",
"Exportaciones (% PIB)",
"Importaciones (% PIB)"
),
Descripción = c(
"PIB dividido por población, en dólares corrientes. Indicador principal del nivel de ingreso y producción económica por persona.",
"Tasa de variación anual del PIB en precios constantes. Refleja la expansión o contracción económica de un país.",
"Flujos netos de inversión con interés gerencial duradero. Fuente crucial de financiamiento externo y transferencia tecnológica.",
"Transferencias personales de migrantes que trabajan en el extranjero. Flujo financiero clave para muchas economías en desarrollo.",
"Valor agregado del sector industrial. Refleja el grado de industrialización y la estructura productiva de una economía.",
"Valor de bienes y servicios vendidos al exterior. Mide el grado de apertura comercial y oportunidades de crecimiento.",
"Valor de bienes y servicios comprados al exterior. Indica la dependencia de la economía respecto al comercio internacional."
),
Interpretación = c(
">20,000 USD: economía desarrollada\n5,000-20,000 USD: economía emergente\n<5,000 USD: economía en desarrollo",
">3%: crecimiento robusto\n0-3%: crecimiento moderado\n<0%: recesión económica",
">5%: alta atracción de IED\n2-5%: nivel moderado\n<2%: baja atracción de inversión",
">10%: alta dependencia\n2-10%: contribución significativa\n<2%: impacto limitado",
">30%: economía industrializada\n20-30%: sector industrial sólido\n<20%: base industrial reducida",
">50%: economía muy abierta\n30-50%: apertura moderada\n<30%: economía relativamente cerrada",
">40%: alta dependencia importaciones\n25-40%: nivel moderado\n<25%: autosuficiencia relativa"
)
)
tabla_1 <- variables_economicas %>%
gt() %>%
tab_header(
title = md("**Tabla 1**"),
subtitle = "Variables Macroeconómicas y su Interpretación"
) %>%
cols_label(
Variable = md("**Variable**"),
Descripción = md("**Descripción**"),
Interpretación = md("**Interpretación**")
) %>%
cols_align(
align = "left",
columns = everything()
) %>%
tab_style(
style = list(
cell_text(weight = "bold", size = "medium", color = "#000000"),
cell_fill(color = "#00e5ff")
),
locations = cells_column_labels()
) %>%
tab_style(
style = cell_borders(
sides = c("top", "bottom"),
color = "#00e5ff",
weight = px(2)
),
locations = list(
cells_column_labels(),
cells_body()
)
) %>%
tab_style(
style = cell_borders(
sides = "right",
color = "#00e5ff",
weight = px(1)
),
locations = cells_body(columns = c(Variable, Descripción))
) %>%
tab_style(
style = list(
cell_fill(color = "#0a0e1a"),
cell_text(color = "#e0e6ed")
),
locations = cells_body()
) %>%
tab_style(
style = cell_text(weight = "bold", color = "#00e5ff"),
locations = cells_body(columns = Variable)
) %>%
tab_style(
style = cell_text(size = "small", color = "#e0e6ed"),
locations = cells_body(columns = c(Descripción, Interpretación))
) %>%
tab_style(
style = list(
cell_text(weight = "bold", color = "#00e5ff", size = "large")
),
locations = cells_title(groups = "title")
) %>%
tab_style(
style = list(
cell_text(color = "#e0e6ed", size = "medium")
),
locations = cells_title(groups = "subtitle")
) %>%
tab_options(
table.font.names = "Times New Roman",
table.width = pct(100),
table.border.top.style = "none",
table.border.bottom.style = "none",
column_labels.border.top.style = "solid",
column_labels.border.top.color = "#00e5ff",
column_labels.border.top.width = px(3),
column_labels.border.bottom.style = "solid",
column_labels.border.bottom.width = px(3),
column_labels.border.bottom.color = "#00e5ff",
table_body.border.bottom.style = "none",
table_body.border.top.style = "none",
table_body.hlines.style = "solid",
table_body.hlines.color = "#00e5ff",
table_body.hlines.width = px(1),
table.background.color = "#0a0e1a",
data_row.padding = px(10),
heading.title.font.size = 18,
heading.subtitle.font.size = 14,
heading.padding = px(12),
heading.border.bottom.style = "solid",
heading.border.bottom.width = px(2),
heading.border.bottom.color = "#00e5ff",
footnotes.padding = px(10),
footnotes.font.size = 13,
source_notes.font.size = 13,
source_notes.padding = px(10)
) %>%
tab_source_note(
source_note = md("**Fuentes:** Elaboración propia con base en World Bank (2023), UN (2015), ECB (2018)")
) %>%
tab_footnote(
footnote = "Los umbrales de interpretación son referenciales y pueden variar según el contexto regional y temporal",
locations = cells_title(groups = "subtitle")
)
tabla_1| Tabla 1 | ||
| Variables Macroeconómicas y su Interpretación1 | ||
| Variable | Descripción | Interpretación |
|---|---|---|
| PIB per cápita (US$) | PIB dividido por población, en dólares corrientes. Indicador principal del nivel de ingreso y producción económica por persona. | >20,000 USD: economía desarrollada 5,000-20,000 USD: economía emergente <5,000 USD: economía en desarrollo |
| Crecimiento del PIB (% anual) | Tasa de variación anual del PIB en precios constantes. Refleja la expansión o contracción económica de un país. | >3%: crecimiento robusto 0-3%: crecimiento moderado <0%: recesión económica |
| Inversión extranjera directa (% PIB) | Flujos netos de inversión con interés gerencial duradero. Fuente crucial de financiamiento externo y transferencia tecnológica. | >5%: alta atracción de IED 2-5%: nivel moderado <2%: baja atracción de inversión |
| Remesas recibidas (% PIB) | Transferencias personales de migrantes que trabajan en el extranjero. Flujo financiero clave para muchas economías en desarrollo. | >10%: alta dependencia 2-10%: contribución significativa <2%: impacto limitado |
| Industria (% PIB) | Valor agregado del sector industrial. Refleja el grado de industrialización y la estructura productiva de una economía. | >30%: economía industrializada 20-30%: sector industrial sólido <20%: base industrial reducida |
| Exportaciones (% PIB) | Valor de bienes y servicios vendidos al exterior. Mide el grado de apertura comercial y oportunidades de crecimiento. | >50%: economía muy abierta 30-50%: apertura moderada <30%: economía relativamente cerrada |
| Importaciones (% PIB) | Valor de bienes y servicios comprados al exterior. Indica la dependencia de la economía respecto al comercio internacional. | >40%: alta dependencia importaciones 25-40%: nivel moderado <25%: autosuficiencia relativa |
| 1 Los umbrales de interpretación son referenciales y pueden variar según el contexto regional y temporal | ||
| Fuentes: Elaboración propia con base en World Bank (2023), UN (2015), ECB (2018) | ||
La inclusión de variables sanitarias responde a que el desarrollo no es puramente económico sino que debe reflejarse en mejoras sustantivas en la calidad de vida, particularmente en indicadores de salud poblacional (Sachs et al., 2022; World Bank, 2023). La esperanza de vida es considerada por organismos internacionales como el indicador sintético más robusto de desarrollo humano, capturando tanto el acceso a servicios de salud como condiciones generales de vida (OECD, 2024). La mortalidad infantil es particularmente sensible a la calidad del sistema sanitario, y el gasto en salud refleja el esfuerzo institucional de un país por asegurar bienestar poblacional (World Bank, 2023)., en la tabla 2 las observamos.
variables_salud <- data.frame(
Variable = c(
"Esperanza de vida al nacer (años)",
"Mortalidad infantil (por cada 1,000 nacidos vivos)",
"Gasto en salud (% del PIB)"
),
Descripción = c(
"Número promedio de años que se espera que viva un recién nacido si los patrones de mortalidad prevalecientes al momento de su nacimiento permanecen constantes a lo largo de su vida. Es uno de los indicadores más robustos para medir el estado de salud poblacional, reflejando la calidad del sistema sanitario, acceso a servicios médicos, condiciones de vida, nutrición y factores ambientales.",
"Número de muertes de niños menores de un año por cada 1,000 nacimientos vivos. Es un indicador sensible de la calidad de atención sanitaria materno-infantil, condiciones sanitarias, acceso a agua potable y nutrición adecuada, funcionando como proxy de desarrollo social y capacidad institucional del sistema de salud.",
"Gasto corriente en salud expresado como porcentaje del PIB, incluyendo tanto gasto público como privado. Refleja la prioridad presupuestaria que un país asigna al sector salud y su capacidad de financiar infraestructura sanitaria, siendo un determinante clave de resultados de salud poblacional."
),
Interpretación = c(
">75 años: salud poblacional avanzada\n70-75 años: nivel medio de desarrollo sanitario\n<70 años: desafíos significativos en salud pública",
"<10: excelentes condiciones sanitarias\n10-25: condiciones moderadas\n>25: necesidades críticas en salud infantil",
">8%: alta prioridad en salud\n5-8%: compromiso moderado\n<5%: recursos sanitarios limitados"
)
)
tabla_2 <- variables_salud %>%
gt() %>%
tab_header(
title = md("**Tabla 2**"),
subtitle = "Indicadores de Salud Pública y su Interpretación"
) %>%
cols_label(
Variable = md("**Variable**"),
Descripción = md("**Descripción**"),
Interpretación = md("**Interpretación**")
) %>%
cols_align(
align = "left",
columns = everything()
) %>%
tab_style(
style = list(
cell_text(weight = "bold", size = "medium", color = "#000000"),
cell_fill(color = "#00e5ff")
),
locations = cells_column_labels()
) %>%
tab_style(
style = cell_borders(
sides = c("top", "bottom"),
color = "#00e5ff",
weight = px(2)
),
locations = list(
cells_column_labels(),
cells_body()
)
) %>%
tab_style(
style = cell_borders(
sides = "right",
color = "#00e5ff",
weight = px(1)
),
locations = cells_body(columns = c(Variable, Descripción))
) %>%
tab_style(
style = list(
cell_fill(color = "#0a0e1a"),
cell_text(color = "#e0e6ed")
),
locations = cells_body()
) %>%
tab_style(
style = cell_text(weight = "bold", color = "#00e5ff"),
locations = cells_body(columns = Variable)
) %>%
tab_style(
style = cell_text(size = "small", color = "#e0e6ed"),
locations = cells_body(columns = c(Descripción, Interpretación))
) %>%
tab_style(
style = list(
cell_text(weight = "bold", color = "#00e5ff", size = "large")
),
locations = cells_title(groups = "title")
) %>%
tab_style(
style = list(
cell_text(color = "#e0e6ed", size = "medium")
),
locations = cells_title(groups = "subtitle")
) %>%
tab_options(
table.font.names = "Times New Roman",
table.width = pct(100),
table.border.top.style = "none",
table.border.bottom.style = "none",
column_labels.border.top.style = "solid",
column_labels.border.top.color = "#00e5ff",
column_labels.border.top.width = px(3),
column_labels.border.bottom.style = "solid",
column_labels.border.bottom.width = px(3),
column_labels.border.bottom.color = "#00e5ff",
table_body.border.bottom.style = "none",
table_body.border.top.style = "none",
table_body.hlines.style = "solid",
table_body.hlines.color = "#00e5ff",
table_body.hlines.width = px(1),
table.background.color = "#0a0e1a",
data_row.padding = px(10),
heading.title.font.size = 18,
heading.subtitle.font.size = 14,
heading.padding = px(12),
heading.border.bottom.style = "solid",
heading.border.bottom.width = px(2),
heading.border.bottom.color = "#00e5ff",
footnotes.padding = px(10),
footnotes.font.size = 13,
source_notes.font.size = 13,
source_notes.padding = px(10)
) %>%
tab_source_note(
source_note = md("**Fuentes:** Elaboración propia con base en WHO (2020), OECD (2024), World Bank (2023)")
) %>%
tab_footnote(
footnote = "Los umbrales de interpretación son referenciales y pueden variar según el contexto regional y nivel de desarrollo",
locations = cells_title(groups = "subtitle")
)
tabla_2| Tabla 2 | ||
| Indicadores de Salud Pública y su Interpretación1 | ||
| Variable | Descripción | Interpretación |
|---|---|---|
| Esperanza de vida al nacer (años) | Número promedio de años que se espera que viva un recién nacido si los patrones de mortalidad prevalecientes al momento de su nacimiento permanecen constantes a lo largo de su vida. Es uno de los indicadores más robustos para medir el estado de salud poblacional, reflejando la calidad del sistema sanitario, acceso a servicios médicos, condiciones de vida, nutrición y factores ambientales. | >75 años: salud poblacional avanzada 70-75 años: nivel medio de desarrollo sanitario <70 años: desafíos significativos en salud pública |
| Mortalidad infantil (por cada 1,000 nacidos vivos) | Número de muertes de niños menores de un año por cada 1,000 nacimientos vivos. Es un indicador sensible de la calidad de atención sanitaria materno-infantil, condiciones sanitarias, acceso a agua potable y nutrición adecuada, funcionando como proxy de desarrollo social y capacidad institucional del sistema de salud. | <10: excelentes condiciones sanitarias 10-25: condiciones moderadas >25: necesidades críticas en salud infantil |
| Gasto en salud (% del PIB) | Gasto corriente en salud expresado como porcentaje del PIB, incluyendo tanto gasto público como privado. Refleja la prioridad presupuestaria que un país asigna al sector salud y su capacidad de financiar infraestructura sanitaria, siendo un determinante clave de resultados de salud poblacional. | >8%: alta prioridad en salud 5-8%: compromiso moderado <5%: recursos sanitarios limitados |
| 1 Los umbrales de interpretación son referenciales y pueden variar según el contexto regional y nivel de desarrollo | ||
| Fuentes: Elaboración propia con base en WHO (2020), OECD (2024), World Bank (2023) | ||
La inclusión de variables tecnológicas es justificada por la importancia creciente de la transformación digital en el desarrollo contemporáneo (UNCTAD, 2021; World Bank, 2023). La acceso a electricidad, internet y telefonía móvil no son lujos sino infraestructuras esenciales que habilitan participación en la economía del conocimiento, acceso a información, servicios financieros y oportunidades económicas (UNCTAD, 2021). La brecha digital ha emergido como una nueva dimensión de desigualdad internacional, donde países con penetración digital menor enfrentan desventajas competitivas significativas (World Bank, 2023)., en la tabla 3 las observamos.
variables_tecnologia <- data.frame(
Variable = c(
"Acceso a electricidad (% de la población)",
"Uso de internet (% de la población)",
"Suscripciones móviles (por cada 100 personas)"
),
Descripción = c(
"Porcentaje de la población con acceso a electricidad. Indicador fundamental de infraestructura energética básica, condición necesaria para actividad económica moderna, educación, salud y conectividad digital.",
"Porcentaje de individuos que han utilizado internet en los últimos 3 meses. Proxy de conectividad digital, acceso a información, y participación en la economía del conocimiento, siendo cada vez más relevante para productividad económica y reducción de brechas informativas.",
"Número de suscripciones a servicios de telefonía celular móvil por cada 100 habitantes. Refleja la penetración de tecnología móvil, que ha sido un vector fundamental de inclusión digital y acceso a servicios financieros en economías en desarrollo."
),
Interpretación = c(
">95%: cobertura eléctrica universal\n80-95%: acceso extendido\n<80%: déficit significativo de infraestructura",
">70%: sociedad digitalmente integrada\n30-70%: adopción media de internet\n<30%: brecha digital significativa",
">100: alta penetración móvil\n80-100: cobertura adecuada\n<80: oportunidades de expansión del mercado"
)
)
tabla_3 <- variables_tecnologia %>%
gt() %>%
tab_header(
title = md("**Tabla 3**"),
subtitle = "Indicadores de Infraestructura y Tecnología"
) %>%
cols_label(
Variable = md("**Variable**"),
Descripción = md("**Descripción**"),
Interpretación = md("**Interpretación**")
) %>%
cols_align(
align = "left",
columns = everything()
) %>%
tab_style(
style = list(
cell_text(weight = "bold", size = "medium", color = "#000000"),
cell_fill(color = "#00e5ff")
),
locations = cells_column_labels()
) %>%
tab_style(
style = cell_borders(
sides = c("top", "bottom"),
color = "#00e5ff",
weight = px(2)
),
locations = list(
cells_column_labels(),
cells_body()
)
) %>%
tab_style(
style = cell_borders(
sides = "right",
color = "#00e5ff",
weight = px(1)
),
locations = cells_body(columns = c(Variable, Descripción))
) %>%
tab_style(
style = list(
cell_fill(color = "#0a0e1a"),
cell_text(color = "#e0e6ed")
),
locations = cells_body()
) %>%
tab_style(
style = cell_text(weight = "bold", color = "#00e5ff"),
locations = cells_body(columns = Variable)
) %>%
tab_style(
style = cell_text(size = "small", color = "#e0e6ed"),
locations = cells_body(columns = c(Descripción, Interpretación))
) %>%
tab_style(
style = list(
cell_text(weight = "bold", color = "#00e5ff", size = "large")
),
locations = cells_title(groups = "title")
) %>%
tab_style(
style = list(
cell_text(color = "#e0e6ed", size = "medium")
),
locations = cells_title(groups = "subtitle")
) %>%
tab_options(
table.font.names = "Times New Roman",
table.width = pct(100),
table.border.top.style = "none",
table.border.bottom.style = "none",
column_labels.border.top.style = "solid",
column_labels.border.top.color = "#00e5ff",
column_labels.border.top.width = px(3),
column_labels.border.bottom.style = "solid",
column_labels.border.bottom.width = px(3),
column_labels.border.bottom.color = "#00e5ff",
table_body.border.bottom.style = "none",
table_body.border.top.style = "none",
table_body.hlines.style = "solid",
table_body.hlines.color = "#00e5ff",
table_body.hlines.width = px(1),
table.background.color = "#0a0e1a",
data_row.padding = px(10),
heading.title.font.size = 18,
heading.subtitle.font.size = 14,
heading.padding = px(12),
heading.border.bottom.style = "solid",
heading.border.bottom.width = px(2),
heading.border.bottom.color = "#00e5ff",
footnotes.padding = px(10),
footnotes.font.size = 13,
source_notes.font.size = 13,
source_notes.padding = px(10)
) %>%
tab_source_note(
source_note = md("**Fuentes:** Elaboración propia con base en World Bank (2023)")
) %>%
tab_footnote(
footnote = "Los valores superiores a 100 en suscripciones móviles indican múltiples suscripciones por persona",
locations = cells_body(
rows = 3,
columns = Interpretación
)
) %>%
tab_footnote(
footnote = "Los umbrales de interpretación son referenciales y pueden variar según el nivel de desarrollo regional",
locations = cells_title(groups = "subtitle")
)
tabla_3| Tabla 3 | ||
| Indicadores de Infraestructura y Tecnología1 | ||
| Variable | Descripción | Interpretación |
|---|---|---|
| Acceso a electricidad (% de la población) | Porcentaje de la población con acceso a electricidad. Indicador fundamental de infraestructura energética básica, condición necesaria para actividad económica moderna, educación, salud y conectividad digital. | >95%: cobertura eléctrica universal 80-95%: acceso extendido <80%: déficit significativo de infraestructura |
| Uso de internet (% de la población) | Porcentaje de individuos que han utilizado internet en los últimos 3 meses. Proxy de conectividad digital, acceso a información, y participación en la economía del conocimiento, siendo cada vez más relevante para productividad económica y reducción de brechas informativas. | >70%: sociedad digitalmente integrada 30-70%: adopción media de internet <30%: brecha digital significativa |
| Suscripciones móviles (por cada 100 personas) | Número de suscripciones a servicios de telefonía celular móvil por cada 100 habitantes. Refleja la penetración de tecnología móvil, que ha sido un vector fundamental de inclusión digital y acceso a servicios financieros en economías en desarrollo. | >100: alta penetración móvil 80-100: cobertura adecuada <80: oportunidades de expansión del mercado2 |
| 1 Los umbrales de interpretación son referenciales y pueden variar según el nivel de desarrollo regional | ||
| 2 Los valores superiores a 100 en suscripciones móviles indican múltiples suscripciones por persona | ||
| Fuentes: Elaboración propia con base en World Bank (2023) | ||
La inclusión de variables ambientales responde al creciente reconocimiento de que el desarrollo sostenible debe integrar consideraciones ecológicas (PNUD, 2023; World Bank, 2023). Aunque el crecimiento económico tradicional ha sido alcanzado frecuentemente mediante degradación ambiental, la sostenibilidad del desarrollo requiere preservación de capital natural, particularmente bosques (para captura de carbono y biodiversidad) y tierra cultivable (para seguridad alimentaria) (PNUD, 2023; World Bank, 2023), en la tabla 4 las vemos.
variables_ambientales <- data.frame(
Variable = c(
"Área boscosa (% del área terrestre)",
"Tierra cultivable (% del área terrestre)"
),
Descripción = c(
"Porcentaje del territorio nacional cubierto por bosques. Es un indicador de conservación ambiental, biodiversidad y sostenibilidad, siendo relevante tanto para mitigación del cambio climático como para servicios ecosistémicos.",
"Porcentaje de tierra apta para cultivos agrícolas. Refleja el potencial agrícola y la base de recursos naturales para producción de alimentos, siendo particularmente relevante para economías con sectores agrícolas significativos."
),
Interpretación = c(
">30%: alta cobertura forestal\n15-30%: cobertura media\n<15%: deforestación significativa",
">20%: alta disponibilidad agrícola\n10-20%: capacidad moderada\n<10%: limitaciones para agricultura"
)
)
tabla_4 <- variables_ambientales %>%
gt() %>%
tab_header(
title = md("**Tabla 4**"),
subtitle = "Indicadores Ambientales y de Uso de la Tierra"
) %>%
cols_label(
Variable = md("**Variable**"),
Descripción = md("**Descripción**"),
Interpretación = md("**Interpretación**")
) %>%
cols_align(
align = "left",
columns = everything()
) %>%
tab_style(
style = list(
cell_text(weight = "bold", size = "medium", color = "#000000"),
cell_fill(color = "#00e5ff")
),
locations = cells_column_labels()
) %>%
tab_style(
style = cell_borders(
sides = c("top", "bottom"),
color = "#00e5ff",
weight = px(2)
),
locations = list(
cells_column_labels(),
cells_body()
)
) %>%
tab_style(
style = cell_borders(
sides = "right",
color = "#00e5ff",
weight = px(1)
),
locations = cells_body(columns = c(Variable, Descripción))
) %>%
tab_style(
style = list(
cell_fill(color = "#0a0e1a"),
cell_text(color = "#e0e6ed")
),
locations = cells_body()
) %>%
tab_style(
style = cell_text(weight = "bold", color = "#00e5ff"),
locations = cells_body(columns = Variable)
) %>%
tab_style(
style = cell_text(size = "small", color = "#e0e6ed"),
locations = cells_body(columns = c(Descripción, Interpretación))
) %>%
tab_style(
style = list(
cell_text(weight = "bold", color = "#00e5ff", size = "large")
),
locations = cells_title(groups = "title")
) %>%
tab_style(
style = list(
cell_text(color = "#e0e6ed", size = "medium")
),
locations = cells_title(groups = "subtitle")
) %>%
tab_options(
table.font.names = "Times New Roman",
table.width = pct(100),
table.border.top.style = "none",
table.border.bottom.style = "none",
column_labels.border.top.style = "solid",
column_labels.border.top.color = "#00e5ff",
column_labels.border.top.width = px(3),
column_labels.border.bottom.style = "solid",
column_labels.border.bottom.width = px(3),
column_labels.border.bottom.color = "#00e5ff",
table_body.border.bottom.style = "none",
table_body.border.top.style = "none",
table_body.hlines.style = "solid",
table_body.hlines.color = "#00e5ff",
table_body.hlines.width = px(1),
table.background.color = "#0a0e1a",
data_row.padding = px(10),
heading.title.font.size = 18,
heading.subtitle.font.size = 14,
heading.padding = px(12),
heading.border.bottom.style = "solid",
heading.border.bottom.width = px(2),
heading.border.bottom.color = "#00e5ff",
footnotes.padding = px(10),
footnotes.font.size = 13,
source_notes.font.size = 13,
source_notes.padding = px(10)
) %>%
tab_source_note(
source_note = md("**Fuentes:** Elaboración propia con base en World Bank (2023)")
) %>%
tab_footnote(
footnote = "Los servicios ecosistémicos incluyen regulación hídrica, conservación de biodiversidad y secuestro de carbono",
locations = cells_body(
rows = 1,
columns = Descripción
)
) %>%
tab_footnote(
footnote = "La tierra cultivable incluye tierras arables, cultivos permanentes y pastos permanentes",
locations = cells_body(
rows = 2,
columns = Descripción
)
) %>%
tab_footnote(
footnote = "Los umbrales de interpretación pueden variar según las características geográficas y ecológicas de cada región",
locations = cells_title(groups = "subtitle")
)
tabla_4| Tabla 4 | ||
| Indicadores Ambientales y de Uso de la Tierra1 | ||
| Variable | Descripción | Interpretación |
|---|---|---|
| Área boscosa (% del área terrestre) | Porcentaje del territorio nacional cubierto por bosques. Es un indicador de conservación ambiental, biodiversidad y sostenibilidad, siendo relevante tanto para mitigación del cambio climático como para servicios ecosistémicos.2 | >30%: alta cobertura forestal 15-30%: cobertura media <15%: deforestación significativa |
| Tierra cultivable (% del área terrestre) | Porcentaje de tierra apta para cultivos agrícolas. Refleja el potencial agrícola y la base de recursos naturales para producción de alimentos, siendo particularmente relevante para economías con sectores agrícolas significativos.3 | >20%: alta disponibilidad agrícola 10-20%: capacidad moderada <10%: limitaciones para agricultura |
| 1 Los umbrales de interpretación pueden variar según las características geográficas y ecológicas de cada región | ||
| 2 Los servicios ecosistémicos incluyen regulación hídrica, conservación de biodiversidad y secuestro de carbono | ||
| 3 La tierra cultivable incluye tierras arables, cultivos permanentes y pastos permanentes | ||
| Fuentes: Elaboración propia con base en World Bank (2023) | ||
La inclusión de variables demográficas es justificada porque la dinámica poblacional condiciona fundamentalmente los desafíos y oportunidades de desarrollo: presión sobre recursos, mercado laboral, demanda por servicios públicos, y sostenibilidad fiscal (CEPAL, 2023; World Bank, 2023). Países con crecimiento poblacional acelerado enfrentan distintos desafíos que aquellos con envejecimiento poblacional, impactando tasas de ahorro, inversión, y provisión de servicios (CEPAL, 2023), vemos las variables en la tabla 5.
variables_demograficas <- data.frame(
Variable = c(
"Población total",
"Crecimiento poblacional (% anual)"
),
Descripción = c(
"Número total de habitantes de un país a mitad de año. El tamaño poblacional determina tanto el mercado interno como la escala de demanda por servicios públicos y recursos naturales.",
"Tasa de variación porcentual anual de la población. Refleja la presión demográfica y sus implicaciones para sostenibilidad, mercados laborales, y provisión de servicios públicos."
),
Interpretación = c(
">100M: país muy poblado\n10-100M: población media\n<10M: país poco poblado",
">2%: crecimiento rápido\n0.5-2%: crecimiento moderado\n<0.5%: crecimiento lento"
)
)
tabla_5 <- variables_demograficas %>%
gt() %>%
tab_header(
title = md("**Tabla 5**"),
subtitle = "Indicadores Demográficos Básicos"
) %>%
cols_label(
Variable = md("**Variable**"),
Descripción = md("**Descripción**"),
Interpretación = md("**Interpretación**")
) %>%
cols_align(
align = "left",
columns = everything()
) %>%
tab_style(
style = list(
cell_text(weight = "bold", size = "medium", color = "#000000"),
cell_fill(color = "#00e5ff")
),
locations = cells_column_labels()
) %>%
tab_style(
style = cell_borders(
sides = c("top", "bottom"),
color = "#00e5ff",
weight = px(2)
),
locations = list(
cells_column_labels(),
cells_body()
)
) %>%
tab_style(
style = cell_borders(
sides = "right",
color = "#00e5ff",
weight = px(1)
),
locations = cells_body(columns = c(Variable, Descripción))
) %>%
tab_style(
style = list(
cell_fill(color = "#0a0e1a"),
cell_text(color = "#e0e6ed")
),
locations = cells_body()
) %>%
tab_style(
style = cell_text(weight = "bold", color = "#00e5ff"),
locations = cells_body(columns = Variable)
) %>%
tab_style(
style = cell_text(size = "small", color = "#e0e6ed"),
locations = cells_body(columns = c(Descripción, Interpretación))
) %>%
tab_style(
style = list(
cell_text(weight = "bold", color = "#00e5ff", size = "large")
),
locations = cells_title(groups = "title")
) %>%
tab_style(
style = list(
cell_text(color = "#e0e6ed", size = "medium")
),
locations = cells_title(groups = "subtitle")
) %>%
tab_options(
table.font.names = "Times New Roman",
table.width = pct(100),
table.border.top.style = "none",
table.border.bottom.style = "none",
column_labels.border.top.style = "solid",
column_labels.border.top.color = "#00e5ff",
column_labels.border.top.width = px(3),
column_labels.border.bottom.style = "solid",
column_labels.border.bottom.width = px(3),
column_labels.border.bottom.color = "#00e5ff",
table_body.border.bottom.style = "none",
table_body.border.top.style = "none",
table_body.hlines.style = "solid",
table_body.hlines.color = "#00e5ff",
table_body.hlines.width = px(1),
table.background.color = "#0a0e1a",
data_row.padding = px(10),
heading.title.font.size = 18,
heading.subtitle.font.size = 14,
heading.padding = px(12),
heading.border.bottom.style = "solid",
heading.border.bottom.width = px(2),
heading.border.bottom.color = "#00e5ff",
footnotes.padding = px(10),
footnotes.font.size = 13,
source_notes.font.size = 13,
source_notes.padding = px(10)
) %>%
tab_source_note(
source_note = md("**Fuentes:** Elaboración propia con base en World Bank (2023)")
) %>%
tab_footnote(
footnote = "La población se refiere a residentes totales independientemente de su estatus legal o ciudadanía",
locations = cells_body(
rows = 1,
columns = Descripción
)
) %>%
tab_footnote(
footnote = "El crecimiento poblacional incluye nacimientos, muertes y migración neta",
locations = cells_body(
rows = 2,
columns = Descripción
)
) %>%
tab_footnote(
footnote = "Los umbrales de interpretación son referenciales y pueden variar según el contexto regional y nivel de desarrollo",
locations = cells_title(groups = "subtitle")
)
tabla_5| Tabla 5 | ||
| Indicadores Demográficos Básicos1 | ||
| Variable | Descripción | Interpretación |
|---|---|---|
| Población total | Número total de habitantes de un país a mitad de año. El tamaño poblacional determina tanto el mercado interno como la escala de demanda por servicios públicos y recursos naturales.2 | >100M: país muy poblado 10-100M: población media <10M: país poco poblado |
| Crecimiento poblacional (% anual) | Tasa de variación porcentual anual de la población. Refleja la presión demográfica y sus implicaciones para sostenibilidad, mercados laborales, y provisión de servicios públicos.3 | >2%: crecimiento rápido 0.5-2%: crecimiento moderado <0.5%: crecimiento lento |
| 1 Los umbrales de interpretación son referenciales y pueden variar según el contexto regional y nivel de desarrollo | ||
| 2 La población se refiere a residentes totales independientemente de su estatus legal o ciudadanía | ||
| 3 El crecimiento poblacional incluye nacimientos, muertes y migración neta | ||
| Fuentes: Elaboración propia con base en World Bank (2023) | ||
A continuacion, se muestra la base de datos que se usara para el modelo de aprendizaje no supervisado.
Base_2022 <- read_csv("f36a5086-3311-4b1a-9f0c-bda5cd4718df_Series - Metadata.csv",
show_col_types = FALSE) %>%
select(
Pais = `Country Name`,
Codigo = `Country Code`,
PIB_per = `GDP per capita (current US$) [NY.GDP.PCAP.CD]`,
Poblacion = `Population, total [SP.POP.TOTL]`,
`Esperanza vida` = `Life expectancy at birth, total (years) [SP.DYN.LE00.IN]`,
`Acceso electricidad` = `Access to electricity (% of population) [EG.ELC.ACCS.ZS]`,
`Area boscosa` = `Forest area (% of land area) [AG.LND.FRST.ZS]`,
`Suscripciones movil` = `Mobile cellular subscriptions (per 100 people) [IT.CEL.SETS.P2]`,
`Crecimiento PIB` = `GDP growth (annual %) [NY.GDP.MKTP.KD.ZG]`,
`Mortalidad infantil` = `Mortality rate, infant (per 1,000 live births) [SP.DYN.IMRT.IN]`,
`Inversion extranjera` = `Foreign direct investment, net inflows (% of GDP) [BX.KLT.DINV.WD.GD.ZS]`,
`Gasto salud` = `Current health expenditure (% of GDP) [SH.XPD.CHEX.GD.ZS]`,
`Uso internet` = `Individuals using the Internet (% of population) [IT.NET.USER.ZS]`,
Importaciones = `Imports of goods and services (% of GDP) [NE.IMP.GNFS.ZS]`,
Exportaciones = `Exports of goods and services (% of GDP) [NE.EXP.GNFS.ZS]`,
`Tierra cultivable` = `Arable land (% of land area) [AG.LND.ARBL.ZS]`,
`Crecimiento poblacion` = `Population growth (annual %) [SP.POP.GROW]`,
Industria = `Industry (including construction), value added (% of GDP) [NV.IND.TOTL.ZS]`,
Remesas = `Personal remittances, received (% of GDP) [BX.TRF.PWKR.DT.GD.ZS]`
)%>%
filter(!Pais %in% c("World", "High income", "Low income", "European Union",
"Latin America & Caribbean", "Middle income", "OECD members",
"East Asia & Pacific", "Sub-Saharan Africa", "South Asia",
"North America", "Euro area", "Arab World", "West Bank and Gaza",
"Lower middle income", "Upper middle income",
"Least developed countries: UN classification",
"Fragile and conflict affected situations",
"Heavily indebted poor countries (HIPC)",
"IDA total", "Low & middle income", "Middle East & North Africa",
"Pacific island small states", "Small states",
"Caribbean small states", "Other small states",
"IDA & IBRD total", "IDA only", "IBRD only",
"Pre-demographic dividend", "Post-demographic dividend",
"Early-demographic dividend", "Late-demographic dividend", "Luxembourg")) %>%
mutate(across(3:19, as.numeric)) %>% drop_na()
tabla_inicial <- datatable(
Base_2022,
extensions = c('Buttons', 'Scroller', 'Responsive', 'FixedHeader'),
options = list(
dom = '<"top"lBf>rt<"bottom"ip><"clear">',
buttons = list(
list(extend = 'copy', text = ' Copiar', className = 'btn-cyber'),
list(extend = 'csv', text = ' CSV', className = 'btn-cyber'),
list(extend = 'excel', text = ' Excel', className = 'btn-cyber'),
list(extend = 'pdf', text = ' PDF', className = 'btn-cyber'),
list(extend = 'print', text = '️ Imprimir', className = 'btn-cyber')
),
pageLength = 12,
lengthMenu = list(c(8, 12, 20, 50, -1),
c('8', '12', '20', '50', 'Todos')),
scrollX = TRUE,
scrollY = "550px",
scroller = TRUE,
deferRender = TRUE,
language = list(
url = '//cdn.datatables.net/plug-ins/1.13.4/i18n/es-ES.json',
search = "Buscar:",
lengthMenu = "Mostrar _MENU_ registros",
info = "_START_ - _END_ de _TOTAL_",
paginate = list(
first = "Primero",
last = "Último",
`next` = "Siguiente",
previous = "Anterior"
)
),
autoWidth = TRUE,
fixedHeader = TRUE,
searchHighlight = TRUE
),
rownames = FALSE,
filter = 'top',
class = c('display', 'compact', 'hover', 'dt-cyber'),
caption = htmltools::HTML(' <span style="color: #00e5ff; font-weight: bold; font-size: 16px;">Indicadores Económicos y Sociales Globales 2022</span>')
) %>%
formatCurrency(
columns = 'PIB_per',
currency = "$",
digits = 0,
before = TRUE
) %>%
formatRound(
columns = 'Poblacion',
digits = 0,
mark = ","
) %>%
formatRound(
columns = c('Esperanza vida', 'Acceso electricidad', 'Area boscosa',
'Suscripciones movil', 'Crecimiento PIB', 'Inversion extranjera',
'Gasto salud', 'Uso internet', 'Importaciones', 'Exportaciones',
'Tierra cultivable', 'Crecimiento poblacion', 'Industria', 'Remesas'),
digits = 2
) %>%
formatRound(
columns = 'Mortalidad infantil',
digits = 1
) %>%
formatStyle(
columns = names(Base_2022),
fontSize = '13px',
fontFamily = 'Arial, sans-serif',
color = '#e0e6ed',
backgroundColor = '#0a0e1a'
) %>%
htmlwidgets::onRender("
function(el, x) {
// Estilizar encabezados
var headers = $('thead th');
headers.css({
'background-color': '#00e5ff !important',
'color': '#000000 !important',
'font-weight': 'bold !important',
'font-size': '14px !important',
'border': '2px solid #00e5ff !important',
'text-transform': 'uppercase',
'letter-spacing': '0.5px'
});
// Estilizar filas
$('tbody tr').css({
'background-color': '#0a0e1a !important',
'border-bottom': '1px solid #00e5ff !important'
});
// Hover effect
$('tbody tr').hover(
function() {
$(this).css({
'background-color': '#12161f !important',
'box-shadow': 'inset 0 0 20px rgba(0, 229, 255, 0.2) !important'
});
},
function() {
$(this).css({
'background-color': '#0a0e1a !important',
'box-shadow': 'none !important'
});
}
);
// Estilizar celdas
$('tbody td').css({
'color': '#e0e6ed !important',
'border-right': '1px solid #00e5ff !important',
'padding': '12px !important'
});
// Estilizar filtros
var filterRow = $('thead tr:last');
filterRow.find('th').css({
'background-color': '#12161f !important',
'border': '1px solid #0084ff !important'
});
filterRow.find('input').css({
'background-color': '#0a0e1a !important',
'color': '#e0e6ed !important',
'border': '1px solid #00e5ff !important',
'border-radius': '6px',
'padding': '8px !important',
'font-size': '12px'
}).attr('placeholder', ' Filtrar...');
// Estilizar botones
var buttons = $('.dt-buttons .btn-cyber');
buttons.css({
'background': 'linear-gradient(135deg, #00e5ff 0%, #0084ff 100%) !important',
'color': '#000000 !important',
'border': '2px solid #00e5ff !important',
'border-radius': '8px !important',
'padding': '10px 16px !important',
'font-weight': 'bold !important',
'font-size': '13px !important',
'cursor': 'pointer !important',
'margin': '5px !important',
'transition': 'all 0.3s ease !important',
'box-shadow': '0 0 15px rgba(0, 229, 255, 0.4) !important'
}).hover(
function() {
$(this).css({
'transform': 'translateY(-3px) !important',
'box-shadow': '0 0 25px rgba(0, 229, 255, 0.8) !important'
});
},
function() {
$(this).css({
'transform': 'translateY(0) !important',
'box-shadow': '0 0 15px rgba(0, 229, 255, 0.4) !important'
});
}
);
// Estilizar paginación
$('.dataTables_paginate .paginate_button').css({
'background-color': '#12161f !important',
'color': '#e0e6ed !important',
'border': '1px solid #00e5ff !important',
'margin': '2px !important',
'padding': '8px 12px !important',
'border-radius': '4px',
'font-size': '12px'
}).hover(
function() {
if (!$(this).hasClass('disabled')) {
$(this).css({
'background-color': '#00e5ff !important',
'color': '#000000 !important'
});
}
},
function() {
$(this).css({
'background-color': '#12161f !important',
'color': '#e0e6ed !important'
});
}
);
$('.dataTables_paginate .paginate_button.current').css({
'background-color': '#00e5ff !important',
'color': '#000000 !important',
'box-shadow': '0 0 15px rgba(0, 229, 255, 0.6) !important'
});
// Estilizar info
$('.dataTables_info').css({
'color': '#e0e6ed !important',
'font-size': '13px'
});
// Estilizar controles
$('label').css({
'color': '#e0e6ed !important',
'font-size': '13px'
});
$('select').css({
'background-color': '#0a0e1a !important',
'color': '#e0e6ed !important',
'border': '1px solid #00e5ff !important',
'border-radius': '4px',
'padding': '6px !important'
});
}
")
tabla_inicialLa implementación del análisis se estructura en cuatro etapas secuenciales, cada una construida sobre los resultados de la anterior, garantizando que la información y patrones descubiertos se preserven y amplifiquen a través del pipeline de análisis.
Previo a cualquier análisis multivariado, es fundamental estandarizar las variables originales para garantizar que todas contribuyan en igualdad de condiciones al cálculo de componentes principales (KeepCoding, 2025). La estandarización se realizó mediante la transformación z-score: \(Z_i = \frac{X_i - \mu_i}{\sigma_i}\) donde \(Z_i\) es la variable estandarizada, \(X_i\) la variable original, \(\mu_i\) la media y \(\sigma_i\) la desviación estándar.
Esta estandarización es crítica porque el análisis de componentes principales se fundamenta en la varianza de los datos: sin estandarizar, variables con escalas numéricas mayores (como población total en millones) dominarían el cálculo de componentes, distorsionando la interpretación y otorgando influencia desproporcionada a magnitudes en lugar de patrones (LinkedIn, 2023; Ciencia de Datos, 2016). Adicionalmente, la estandarización garantiza que el análisis capture relaciones entre variables y no simplemente diferencias en escala.
Con las 17 variables estandarizadas, se aplica el Análisis de Componentes Principales para transformar el conjunto de variables originales, potencialmente correlacionadas, en un conjunto menor de componentes principales ortogonales (Jolliffe, 2002; OpenWebinars, 2025). El ACP identifica las direcciones en el espacio de datos donde la varianza es máxima, creando nuevas dimensiones (componentes) que son combinaciones lineales ponderadas de las variables originales (Jolliffe, 2002; KeepCoding, 2025).
Matemáticamente, el ACP comienza construyendo la matriz de covarianza \(C\) de las variables estandarizadas, cuyas entradas representan cómo varían conjuntamente pares de variables (KeepCoding, 2025). Los vectores propios de esta matriz de covarianza definen las direcciones principales (componentes), ordenados según sus correspondientes valores propios, que representan la cantidad de varianza explicada en cada dirección (Jolliffe, 2002). El primer componente principal captura la máxima varianza; el segundo, la máxima varianza restante sujeto a ortogonalidad respecto al primero; y así sucesivamente (Jolliffe, 2002).
El objetivo es identificar cuántos componentes son necesarios para capturar la mayor parte de la varianza total de los datos—típicamente entre 70-90% según el contexto (OpenWebinars, 2025). Esto permite reducir significativamente la dimensionalidad: en lugar de trabajar con 17 variables potencialmente redundantes, se trabaja con un número reducido de componentes sintéticos que capturan la esencia de la heterogeneidad internacional (Jolliffe, 2002).
Una vez obtenidos los componentes principales, se utiliza la distancia euclidiana como métrica de disimilaridad entre países. Para cada par de países, la distancia euclidiana se calcula como:
\[ d_{ij} = \sqrt{\sum_{k=1}^{p} (PC_{ik} - PC_{jk})^2} \] Donde:
Esta distancia mide la proximidad multidimensional entre países: distancias pequeñas indican perfiles similares, distancias grandes indican disimilaridad (Universidad de Granada, 2016; ArcGIS, 2024).
La distancia euclidiana es particularmente apropiada para el método de Ward porque, en su implementación aglomerativa, se utiliza el cuadrado de la distancia euclidiana—formalmente conocida como “distancia euclidiana semicuadrada”—como medida de disimilaridad (Ward, 1963; Wikipedia, 2013; TIBCO, 2024).
El método de Ward es un algoritmo jerárquico aglomerativo que opera iterativamente sobre el conjunto de países para formar una jerarquía de clusters (Ward, 1963). El procedimiento inicia considerando cada país como un cluster individual independiente, creando n grupos iniciales. En cada iteración subsecuente, se identifican los dos clusters más próximos según el criterio de Ward y se fusionan en un único cluster más grande (Ward, 1963; Universidad de Granada, 2016; ICESI, 2025).
El criterio de Ward minimiza específicamente la suma total de cuadrados dentro de los clusters (within-cluster sum of squares, WCSS). Matemáticamente, en cada paso, Ward selecciona el par de clusters cuya fusión produce el incremento mínimo en la varianza total intra-cluster (Ward, 1963; Wikipedia, 2013).
El algoritmo se ejecuta recursivamente hasta que todos los países quedan englobados en un único cluster. El resultado es un dendrograma—diagrama en forma de árbol invertido—que visualiza el proceso completo de fusión: cada rama representa un país individual, cada nodo de fusión representa la unión de dos clusters, y la altura de cada nodo indica el nivel de disimilaridad en el cual ocurrió la fusión (Universidad de Granada, 2016; ICESI, 2025). El dendrograma permite identificar visualmente el número óptimo de clusters “cortando” el árbol a un nivel específico de altura, determinando así cuántos grupos finales son más interpretables y útiles (Ward, 1963; Universidad de Granada, 2016).
En síntesis, el modelo integra: (1) estandarización para igualar contribuciones relativas, (2) reducción de dimensionalidad mediante ACP para simplificar sin perder información, (3) cálculo de distancias euclidianas para cuantificar disimilaridad, y (4) clusterización jerárquica Ward para crear una taxonomía multidimensional de desarrollo. Esta arquitectura metodológica asegura que los agrupamientos emergentes sean producto exclusivamente de los datos y no de imposiciones externas, permitiendo descubrimientos genuinos sobre la estructura del desarrollo internacional (Jolliffe, 2002; Charrad et al., 2014).
variables_numericas <- names(Base_2022)[3:ncol(Base_2022)]
crear_tabla_unificada <- function(data, variable) {
valores <- data[[variable]]
total_paises <- sum(!is.na(valores))
media <- round(mean(valores, na.rm = TRUE), 2)
mediana <- round(median(valores, na.rm = TRUE), 2)
desv_est <- round(sd(valores, na.rm = TRUE), 2)
q1 <- round(quantile(valores, 0.25, na.rm = TRUE), 2)
q3 <- round(quantile(valores, 0.75, na.rm = TRUE), 2)
minimo <- round(min(valores, na.rm = TRUE), 2)
maximo <- round(max(valores, na.rm = TRUE), 2)
top10 <- data %>%
select(Pais, Valor = all_of(variable)) %>%
arrange(desc(Valor)) %>%
head(10) %>%
mutate(
Ranking = row_number(),
Pct_vs_Media = round((Valor / media - 1) * 100, 1)
)
estadisticas <- data.frame(
Métrica = c("Total Países", "Media", "Mediana", "Desv. Est.",
"Q1", "Q3", "Mínimo", "Máximo"),
Valor = c(total_paises, media, mediana, desv_est, q1, q3, minimo, maximo)
)
top10_tabla <- top10 %>%
mutate(
Pct_Display = paste0(ifelse(Pct_vs_Media >= 0, "+", ""), Pct_vs_Media, "%"),
Pct_Color = ifelse(Pct_vs_Media >= 0, "#00e676", "#ff1744")
) %>%
select(Ranking, País = Pais, Valor, Pct_Display, Pct_Color)
list(estadisticas = estadisticas, top10 = top10_tabla)
}for (variable in variables_numericas) {
cat(sprintf('\n\n#### %s {.unnumbered}\n\n', variable))
datos <- crear_tabla_unificada(Base_2022, variable)
cat('<div class="two-column-layout">\n\n')
cat('<div class="table-container">\n\n')
cat('<p class="section-title"> Estadísticas Globales</p>\n\n')
tabla_stats <- datos$estadisticas %>%
kbl(
align = c('l', 'r'),
escape = FALSE,
col.names = c("Métrica", "Valor")
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = TRUE,
font_size = 13
) %>%
row_spec(0, background = "#00e5ff", color = "#000", bold = TRUE, font_size = 14) %>%
row_spec(1, background = "#12161f", color = "#00e5ff", bold = TRUE, font_size = 14) %>%
row_spec(2:8, background = "#0d1117", color = "#e0e6ed") %>%
column_spec(1, width = "14em", bold = TRUE, color = "#e0e6ed") %>%
column_spec(2, width = "10em", color = "#00e5ff", bold = TRUE)
print(tabla_stats)
cat('\n\n</div>\n\n')
cat('<div class="table-container">\n\n')
cat('<p class="section-title"> Top 10 Países</p>\n\n')
tabla_top10_data <- datos$top10 %>%
mutate(
Pct_Display_Colored = cell_spec(
Pct_Display,
"html",
color = Pct_Color,
bold = TRUE
)
) %>%
select(`#` = Ranking, País, Valor, `% vs Media` = Pct_Display_Colored)
tabla_top10 <- tabla_top10_data %>%
kbl(
align = c('c', 'l', 'r', 'c'),
escape = FALSE
) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = TRUE,
font_size = 13
) %>%
row_spec(0, background = "#0084ff", color = "#000", bold = TRUE, font_size = 14) %>%
row_spec(1:10, background = "#0d1117", color = "#e0e6ed") %>%
column_spec(1, width = "3em", bold = TRUE, color = "#000", background = "#00e5ff") %>%
column_spec(2, width = "13em", bold = TRUE) %>%
column_spec(3, width = "9em", color = "#00e5ff", bold = TRUE)
print(tabla_top10)
cat('\n\n</div>\n\n')
cat('</div>\n\n')
}Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 17045.36 |
| Mediana | 6705.15 |
| Desv. Est. | 22688.73 |
| Q1 | 2610.30 |
| Q3 | 21062.53 |
| Mínimo | 250.63 |
| Máximo | 109269.52 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Norway | 109269.52 | +541.1% |
| 2 | Ireland | 105234.51 | +517.4% |
| 3 | Switzerland | 94394.51 | +453.8% |
| 4 | Qatar | 88701.46 | +420.4% |
| 5 | United States | 77860.91 | +356.8% |
| 6 | Iceland | 75121.02 | +340.7% |
| 7 | Denmark | 68091.32 | +299.5% |
| 8 | Australia | 64997.01 | +281.3% |
| 9 | Netherlands | 59123.32 | +246.9% |
| 10 | Sweden | 55296.94 | +224.4% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140 |
| Media | 49640844 |
| Mediana | 10435607 |
| Desv. Est. | 173452511 |
| Q1 | 2949316 |
| Q3 | 33230724 |
| Mínimo | 33755 |
| Máximo | 1425423212 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | India | 1425423212 | +2771.5% |
| 2 | China | 1412175000 | +2744.8% |
| 3 | United States | 334017321 | +572.9% |
| 4 | Indonesia | 278830529 | +461.7% |
| 5 | Pakistan | 243700667 | +390.9% |
| 6 | Brazil | 210306415 | +323.7% |
| 7 | Bangladesh | 169384897 | +241.2% |
| 8 | Russian Federation | 144236933 | +190.6% |
| 9 | Mexico | 128613117 | +159.1% |
| 10 | Japan | 125124989 | +152.1% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 73.46 |
| Mediana | 74.35 |
| Desv. Est. | 6.73 |
| Q1 | 68.16 |
| Q3 | 78.05 |
| Mínimo | 56.81 |
| Máximo | 85.71 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | San Marino | 85.70800 | +16.7% |
| 2 | Japan | 83.99634 | +14.3% |
| 3 | Switzerland | 83.60488 | +13.8% |
| 4 | Australia | 83.20000 | +13.3% |
| 5 | Spain | 83.13415 | +13.2% |
| 6 | Sweden | 83.05854 | +13.1% |
| 7 | Israel | 82.70000 | +12.6% |
| 8 | Italy | 82.70000 | +12.6% |
| 9 | Korea, Rep. | 82.68049 | +12.6% |
| 10 | Ireland | 82.50976 | +12.3% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 88.23 |
| Mediana | 100.00 |
| Desv. Est. | 22.08 |
| Q1 | 90.95 |
| Q3 | 100.00 |
| Mínimo | 10.30 |
| Máximo | 100.00 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Albania | 100 | +13.3% |
| 2 | Algeria | 100 | +13.3% |
| 3 | Antigua and Barbuda | 100 | +13.3% |
| 4 | Argentina | 100 | +13.3% |
| 5 | Armenia | 100 | +13.3% |
| 6 | Australia | 100 | +13.3% |
| 7 | Austria | 100 | +13.3% |
| 8 | Azerbaijan | 100 | +13.3% |
| 9 | Bahamas, The | 100 | +13.3% |
| 10 | Belarus | 100 | +13.3% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 30.62 |
| Mediana | 30.66 |
| Desv. Est. | 20.77 |
| Q1 | 11.82 |
| Q3 | 46.22 |
| Mínimo | 0.00 |
| Máximo | 90.09 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Solomon Islands | 90.08610 | +194.2% |
| 2 | Finland | 73.72650 | +140.8% |
| 3 | Bhutan | 71.55218 | +133.7% |
| 4 | Guinea-Bissau | 69.81259 | +128% |
| 5 | Sweden | 68.69967 | +124.4% |
| 6 | Japan | 68.40878 | +123.4% |
| 7 | Korea, Rep. | 64.21107 | +109.7% |
| 8 | Congo, Rep. | 64.17570 | +109.6% |
| 9 | Fiji | 63.12972 | +106.2% |
| 10 | Timor-Leste | 61.75521 | +101.7% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 116.43 |
| Mediana | 116.33 |
| Desv. Est. | 31.30 |
| Q1 | 101.07 |
| Q3 | 135.29 |
| Mínimo | 39.71 |
| Máximo | 207.28 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Montenegro | 207.278 | +78% |
| 2 | Antigua and Barbuda | 200.541 | +72.2% |
| 3 | El Salvador | 183.249 | +57.4% |
| 4 | Botswana | 178.205 | +53.1% |
| 5 | Thailand | 176.223 | +51.4% |
| 6 | Japan | 168.603 | +44.8% |
| 7 | Russian Federation | 168.476 | +44.7% |
| 8 | Kuwait | 168.350 | +44.6% |
| 9 | Mauritius | 164.309 | +41.1% |
| 10 | Qatar | 162.249 | +39.4% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 4.53 |
| Mediana | 4.52 |
| Desv. Est. | 4.25 |
| Q1 | 2.69 |
| Q3 | 6.30 |
| Mínimo | -20.54 |
| Máximo | 19.79 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Fiji | 19.792727 | +336.9% |
| 2 | Cabo Verde | 15.843676 | +249.8% |
| 3 | Maldives | 13.826090 | +205.2% |
| 4 | Armenia | 12.600000 | +178.1% |
| 5 | Saudi Arabia | 12.000587 | +164.9% |
| 6 | Niger | 11.900000 | +162.7% |
| 7 | Georgia | 10.958532 | +141.9% |
| 8 | Bahamas, The | 10.877455 | +140.1% |
| 9 | Panama | 10.769666 | +137.7% |
| 10 | Belize | 9.652978 | +113.1% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 17.15 |
| Mediana | 11.40 |
| Desv. Est. | 16.10 |
| Q1 | 4.05 |
| Q3 | 24.77 |
| Mínimo | 1.40 |
| Máximo | 68.30 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Niger | 68.3 | +298.3% |
| 2 | Guinea | 63.1 | +267.9% |
| 3 | Mali | 59.0 | +244% |
| 4 | Sierra Leone | 58.0 | +238.2% |
| 5 | Lesotho | 57.6 | +235.9% |
| 6 | Pakistan | 51.8 | +202% |
| 7 | Cote d’Ivoire | 47.9 | +179.3% |
| 8 | Benin | 47.7 | +178.1% |
| 9 | Mozambique | 46.5 | +171.1% |
| 10 | Burkina Faso | 46.1 | +168.8% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 4.17 |
| Mediana | 2.55 |
| Desv. Est. | 11.07 |
| Q1 | 1.37 |
| Q3 | 4.72 |
| Mínimo | -8.42 |
| Máximo | 126.08 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Malta | 126.08409 | +2923.6% |
| 2 | Antigua and Barbuda | 16.78323 | +302.5% |
| 3 | Mozambique | 16.00429 | +283.8% |
| 4 | Mauritania | 14.66442 | +251.7% |
| 5 | Mongolia | 14.60531 | +250.2% |
| 6 | Montenegro | 14.00620 | +235.9% |
| 7 | Uruguay | 12.48041 | +199.3% |
| 8 | Maldives | 11.84548 | +184.1% |
| 9 | Senegal | 10.54112 | +152.8% |
| 10 | Gambia, The | 10.49959 | +151.8% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 6.96 |
| Mediana | 7.09 |
| Desv. Est. | 2.77 |
| Q1 | 4.48 |
| Q3 | 8.89 |
| Mínimo | 2.18 |
| Máximo | 16.50 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | United States | 16.49614 | +137% |
| 2 | Timor-Leste | 14.32455 | +105.8% |
| 3 | Lesotho | 12.65128 | +81.8% |
| 4 | Germany | 12.60513 | +81.1% |
| 5 | France | 11.88190 | +70.7% |
| 6 | Marshall Islands | 11.73604 | +68.6% |
| 7 | Switzerland | 11.70653 | +68.2% |
| 8 | Japan | 11.42184 | +64.1% |
| 9 | Austria | 11.15729 | +60.3% |
| 10 | United Kingdom | 11.05088 | +58.8% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 70.47 |
| Mediana | 78.71 |
| Desv. Est. | 24.39 |
| Q1 | 55.78 |
| Q3 | 89.23 |
| Mínimo | 11.00 |
| Máximo | 100.00 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Saudi Arabia | 100.0000 | +41.9% |
| 2 | Iceland | 99.8082 | +41.6% |
| 3 | Kuwait | 99.7237 | +41.5% |
| 4 | Qatar | 99.6528 | +41.4% |
| 5 | Norway | 99.0000 | +40.5% |
| 6 | Denmark | 97.8601 | +38.9% |
| 7 | Malaysia | 97.3986 | +38.2% |
| 8 | Korea, Rep. | 97.1686 | +37.9% |
| 9 | Australia | 97.0424 | +37.7% |
| 10 | Ireland | 96.6206 | +37.1% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 51.02 |
| Mediana | 46.08 |
| Desv. Est. | 26.23 |
| Q1 | 30.83 |
| Q3 | 64.03 |
| Mínimo | 15.06 |
| Máximo | 173.02 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | San Marino | 173.02372 | +239.1% |
| 2 | Djibouti | 143.03467 | +180.4% |
| 3 | Malta | 115.00492 | +125.4% |
| 4 | Slovak Republic | 104.93886 | +105.7% |
| 5 | Cyprus | 102.01066 | +99.9% |
| 6 | Belgium | 96.69985 | +89.5% |
| 7 | Lesotho | 95.86760 | +87.9% |
| 8 | Ireland | 95.44505 | +87.1% |
| 9 | Hungary | 94.30488 | +84.8% |
| 10 | North Macedonia | 93.36196 | +83% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 45.73 |
| Mediana | 41.40 |
| Desv. Est. | 29.28 |
| Q1 | 26.03 |
| Q3 | 55.53 |
| Mínimo | 4.97 |
| Máximo | 197.41 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | San Marino | 197.41235 | +331.7% |
| 2 | Djibouti | 159.25074 | +248.2% |
| 3 | Ireland | 136.68444 | +198.9% |
| 4 | Malta | 128.41046 | +180.8% |
| 5 | Cyprus | 105.62177 | +131% |
| 6 | Slovak Republic | 98.99011 | +116.5% |
| 7 | Netherlands | 96.44362 | +110.9% |
| 8 | Belgium | 95.23960 | +108.3% |
| 9 | Slovenia | 93.98266 | +105.5% |
| 10 | Viet Nam | 93.42013 | +104.3% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 16.23 |
| Mediana | 12.41 |
| Desv. Est. | 14.09 |
| Q1 | 5.13 |
| Q3 | 24.06 |
| Mínimo | 0.13 |
| Máximo | 60.78 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Bangladesh | 60.78382 | +274.5% |
| 2 | Denmark | 59.00000 | +263.5% |
| 3 | Moldova | 56.75182 | +249.7% |
| 4 | India | 51.80548 | +219.2% |
| 5 | Burundi | 50.37027 | +210.4% |
| 6 | Rwanda | 50.20054 | +209.3% |
| 7 | Togo | 48.72219 | +200.2% |
| 8 | Hungary | 45.55853 | +180.7% |
| 9 | Gambia, The | 43.47826 | +167.9% |
| 10 | Pakistan | 39.21492 | +141.6% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 1.13 |
| Mediana | 1.00 |
| Desv. Est. | 1.38 |
| Q1 | 0.29 |
| Q3 | 1.99 |
| Mínimo | -3.17 |
| Máximo | 5.91 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Qatar | 5.907018 | +422.7% |
| 2 | Kuwait | 5.113181 | +352.5% |
| 3 | Oman | 4.980137 | +340.7% |
| 4 | Saudi Arabia | 4.418920 | +291.1% |
| 5 | Niger | 3.251706 | +187.8% |
| 6 | Congo, Dem. Rep. | 3.223402 | +185.3% |
| 7 | Angola | 3.143026 | +178.1% |
| 8 | Mali | 3.009426 | +166.3% |
| 9 | Uganda | 3.007595 | +166.2% |
| 10 | Tanzania | 2.950467 | +161.1% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 27.00 |
| Mediana | 25.26 |
| Desv. Est. | 11.60 |
| Q1 | 19.96 |
| Q3 | 31.75 |
| Mínimo | 2.39 |
| Máximo | 65.77 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Kuwait | 65.76633 | +143.6% |
| 2 | Qatar | 65.34890 | +142% |
| 3 | Iraq | 65.27212 | +141.7% |
| 4 | Oman | 59.48521 | +120.3% |
| 5 | Azerbaijan | 56.14674 | +108% |
| 6 | Timor-Leste | 54.51234 | +101.9% |
| 7 | Saudi Arabia | 53.12377 | +96.8% |
| 8 | Congo, Rep. | 49.24555 | +82.4% |
| 9 | Norway | 49.12890 | +82% |
| 10 | Congo, Dem. Rep. | 47.77963 | +77% |
Estadísticas Globales
| Métrica | Valor |
|---|---|
| Total Países | 140.00 |
| Media | 5.87 |
| Mediana | 2.18 |
| Desv. Est. | 9.39 |
| Q1 | 0.46 |
| Q3 | 6.74 |
| Mínimo | 0.01 |
| Máximo | 53.22 |
Top 10 Países
| # | País | Valor | % vs Media |
|---|---|---|---|
| 1 | Nepal | 53.22215 | +806.7% |
| 2 | Tajikistan | 49.89531 | +750% |
| 3 | Tonga | 41.94160 | +614.5% |
| 4 | Samoa | 33.61166 | +472.6% |
| 5 | Lebanon | 30.65552 | +422.2% |
| 6 | Honduras | 27.00110 | +360% |
| 7 | Kyrgyz Republic | 26.57756 | +352.8% |
| 8 | El Salvador | 24.63437 | +319.7% |
| 9 | Gambia, The | 22.76212 | +287.8% |
| 10 | Lesotho | 22.61587 | +285.3% |
preparar_top15 <- function(data, variable, nombre_var) {
resultado <- data %>%
filter(!is.na(!!sym(variable)) & !!sym(variable) > 0) %>%
arrange(desc(!!sym(variable))) %>%
slice_head(n = 15) %>%
arrange(!!sym(variable)) %>%
mutate(
Pais_label = Pais,
Valor = !!sym(variable),
Nombre_Variable = nombre_var
) %>%
select(Pais_label, Valor, Nombre_Variable)
return(resultado)
}
vars_config <- list(
list(var = "PIB_per", nombre = "PIB per cápita (US$)", color = "#00e676"),
list(var = "Crecimiento PIB", nombre = "Crecimiento PIB (% anual)", color = "#0084ff"),
list(var = "Inversion extranjera", nombre = "Inversión Extranjera Directa (% PIB)", color = "#ffd600"),
list(var = "Remesas", nombre = "Remesas recibidas (% PIB)", color = "#a259ff"),
list(var = "Industria", nombre = "Industria (% PIB)", color = "#ff6b00"),
list(var = "Exportaciones", nombre = "Exportaciones (% PIB)", color = "#00e5ff"),
list(var = "Importaciones", nombre = "Importaciones (% PIB)", color = "#ff1744")
)
datasets <- lapply(seq_along(vars_config), function(i) {
config <- vars_config[[i]]
preparar_top15(Base_2022, config$var, config$nombre)
})
p <- plot_ly()
for (i in seq_along(vars_config)) {
config <- vars_config[[i]]
if(nrow(datasets[[i]]) > 0) {
p <- p %>%
add_trace(
x = datasets[[i]]$Valor,
y = datasets[[i]]$Pais_label,
type = 'bar',
orientation = 'h',
marker = list(
color = config$color,
line = list(color = '#ffffff', width = 1.5)
),
text = format(round(datasets[[i]]$Valor, 2), big.mark = ",", scientific = FALSE),
textposition = 'outside',
textfont = list(color = '#00e5ff', size = 13, family = "Arial"),
customdata = datasets[[i]]$Nombre_Variable,
# ✅ Hover template CORREGIDO - colores que siempre contrastan
hovertemplate = paste0(
"<b style='color:#000000; font-size:14px; background-color:#ffffff; padding:5px; border-radius:3px;'>%{y}</b><br>",
"<span style='color:#1a1a1a;'><b>%{customdata}:</b></span><br>",
"<b style='color:#b35900; font-size:16px;'>%{x:.2f}</b>",
"<extra></extra>"
),
name = config$nombre,
visible = (i == 1),
showlegend = FALSE
)
}
}
p %>%
layout(
title = list(
text = paste0(
"<b style='color:#00e5ff; font-size:24px;'>Top 15 Países - ",
vars_config[[1]]$nombre,
"</b><br>",
"<span style='color:#8b92a0; font-size:14px;'>Año 2022 | Selecciona una variable para cambiar</span>"
),
x = 0.5,
xanchor = 'center',
y = 0.95
),
xaxis = list(
title = paste0("<b style='font-size:16px;'>", vars_config[[1]]$nombre, "</b>"),
gridcolor = '#12161f',
showgrid = TRUE,
zeroline = TRUE,
zerolinewidth = 2,
zerolinecolor = "rgba(0, 229, 255, 0.5)",
tickfont = list(color = '#8b92a0', size = 13),
titlefont = list(color = '#e0e6ed', size = 16),
range = c(0, max(datasets[[1]]$Valor) * 1.15)
),
yaxis = list(
title = "<b style='font-size:16px;'>País</b>",
tickfont = list(color = '#e0e6ed', size = 13),
titlefont = list(color = '#e0e6ed', size = 16),
categoryorder = "array",
categoryarray = rev(datasets[[1]]$Pais_label),
automargin = TRUE
),
plot_bgcolor = '#000000',
paper_bgcolor = '#0a0e1a',
font = list(family = "Arial, sans-serif", color = '#e0e6ed', size = 13),
margin = list(l = 180, r = 50, b = 80, t = 120),
hovermode = 'closest',
hoverlabel = list(
bgcolor = "#ffffff",
bordercolor = "#00e5ff",
font = list(color = "#000000", size = 13, family = "Arial")
),
updatemenus = list(
list(
buttons = lapply(seq_along(vars_config), function(i) {
config <- vars_config[[i]]
visible <- rep(FALSE, length(vars_config))
visible[i] <- TRUE
list(
label = strsplit(config$nombre, " \\(")[[1]][1],
method = "update",
args = list(
list(visible = visible),
list(
title = paste0(
"<b style='color:#00e5ff; font-size:24px;'>Top 15 Países - ",
config$nombre,
"</b><br>",
"<span style='color:#8b92a0; font-size:14px;'>Año 2022 | Selecciona una variable para cambiar</span>"
),
"xaxis.title" = paste0("<b style='font-size:16px;'>", config$nombre, "</b>"),
"xaxis.range" = c(0, max(datasets[[i]]$Valor) * 1.15),
"yaxis.categoryarray" = rev(datasets[[i]]$Pais_label)
)
)
)
}),
direction = "down",
pad = list(r = 10, t = 10),
showactive = TRUE,
x = 0.02,
xanchor = "left",
y = 1.02,
yanchor = "bottom",
bgcolor = "rgba(162, 89, 255, 0.25)",
bordercolor = "#a259ff",
borderwidth = 2,
font = list(size = 12, color = "#a259ff", family = "Arial")
)
)
) %>%
config(
responsive = TRUE,
displayModeBar = TRUE,
displaylogo = FALSE,
modeBarButtonsToRemove = list('lasso2d', 'select2d'),
toImageButtonOptions = list(
format = "png",
filename = "top15_economia_2022",
width = 1600,
height = 900
)
)# Asignar continentes
asignar_continentes <- function(data) {
continentes_map <- c(
"Argentina" = "Americas", "Bahamas, The" = "Americas", "Barbados" = "Americas",
"Belize" = "Americas", "Bolivia" = "Americas", "Brazil" = "Americas",
"Canada" = "Americas", "Chile" = "Americas", "Colombia" = "Americas",
"Costa Rica" = "Americas", "Cuba" = "Americas", "Dominica" = "Americas",
"Dominican Republic" = "Americas", "Ecuador" = "Americas", "El Salvador" = "Americas",
"Grenada" = "Americas", "Guatemala" = "Americas", "Guyana" = "Americas",
"Haiti" = "Americas", "Honduras" = "Americas", "Jamaica" = "Americas",
"Mexico" = "Americas", "Nicaragua" = "Americas", "Panama" = "Americas",
"Paraguay" = "Americas", "Peru" = "Americas", "St. Kitts and Nevis" = "Americas",
"St. Lucia" = "Americas", "St. Vincent and the Grenadines" = "Americas",
"Suriname" = "Americas", "Trinidad and Tobago" = "Americas", "United States" = "Americas",
"Uruguay" = "Americas", "Venezuela, RB" = "Americas", "Antigua and Barbuda" = "Americas",
"Albania" = "Europe", "Austria" = "Europe", "Belarus" = "Europe",
"Belgium" = "Europe", "Bosnia and Herzegovina" = "Europe", "Bulgaria" = "Europe",
"Croatia" = "Europe", "Cyprus" = "Europe", "Czech Republic" = "Europe",
"Czechia" = "Europe", "Denmark" = "Europe", "Estonia" = "Europe",
"Finland" = "Europe", "France" = "Europe", "Germany" = "Europe",
"Greece" = "Europe", "Hungary" = "Europe", "Iceland" = "Europe",
"Ireland" = "Europe", "Italy" = "Europe", "Kosovo" = "Europe",
"Latvia" = "Europe", "Lithuania" = "Europe", "Luxembourg" = "Europe",
"Malta" = "Europe", "Montenegro" = "Europe", "Netherlands" = "Europe",
"North Macedonia" = "Europe", "Norway" = "Europe", "Poland" = "Europe",
"Portugal" = "Europe", "Russian Federation" = "Europe", "Serbia" = "Europe",
"Slovak Republic" = "Europe", "Slovakia" = "Europe", "Slovenia" = "Europe",
"Spain" = "Europe", "Sweden" = "Europe", "Switzerland" = "Europe",
"Turkey" = "Europe", "Turkiye" = "Europe", "Ukraine" = "Europe",
"United Kingdom" = "Europe", "Armenia" = "Europe", "Azerbaijan" = "Europe",
"Georgia" = "Europe", "Moldova" = "Europe", "Romania" = "Europe",
"San Marino" = "Europe",
"Afghanistan" = "Asia", "Bahrain" = "Asia", "Bangladesh" = "Asia",
"Bhutan" = "Asia", "Brunei Darussalam" = "Asia", "Cambodia" = "Asia",
"China" = "Asia", "Hong Kong SAR, China" = "Asia", "India" = "Asia",
"Indonesia" = "Asia", "Iran, Islamic Rep." = "Asia", "Iraq" = "Asia",
"Israel" = "Asia", "Japan" = "Asia", "Jordan" = "Asia",
"Kazakhstan" = "Asia", "Korea, Dem. People's rep." = "Asia", "Korea, Rep." = "Asia",
"Kuwait" = "Asia", "Kyrgyz Republic" = "Asia", "Lao PDR" = "Asia",
"Lebanon" = "Asia", "Macao SAR, China" = "Asia", "Malaysia" = "Asia",
"Maldives" = "Asia", "Mongolia" = "Asia", "Myanmar" = "Asia",
"Nepal" = "Asia", "Oman" = "Asia", "Pakistan" = "Asia",
"Philippines" = "Asia", "Qatar" = "Asia", "Saudi Arabia" = "Asia",
"Singapore" = "Asia", "Sri Lanka" = "Asia", "Syrian Arab Republic" = "Asia",
"Taiwan" = "Asia", "Tajikistan" = "Asia", "Thailand" = "Asia",
"Timor-Leste" = "Asia", "Turkmenistan" = "Asia", "United Arab Emirates" = "Asia",
"Uzbekistan" = "Asia", "Vietnam" = "Asia", "Viet Nam" = "Asia",
"West Bank and Gaza" = "Asia", "Yemen, Rep." = "Asia",
"Algeria" = "Africa", "Angola" = "Africa", "Benin" = "Africa",
"Botswana" = "Africa", "Burkina Faso" = "Africa", "Burundi" = "Africa",
"Cabo Verde" = "Africa", "Cameroon" = "Africa", "Central African Republic" = "Africa",
"Chad" = "Africa", "Comoros" = "Africa", "Congo, Dem. Rep." = "Africa",
"Congo, Rep." = "Africa", "Cote d'Ivoire" = "Africa", "Djibouti" = "Africa",
"Egypt, Arab Rep." = "Africa", "Equatorial Guinea" = "Africa", "Eritrea" = "Africa",
"Eswatini" = "Africa", "Ethiopia" = "Africa", "Gabon" = "Africa",
"Gambia, The" = "Africa", "Ghana" = "Africa", "Guinea" = "Africa",
"Guinea-Bissau" = "Africa", "Kenya" = "Africa", "Lesotho" = "Africa",
"Liberia" = "Africa", "Libya" = "Africa", "Madagascar" = "Africa",
"Malawi" = "Africa", "Mali" = "Africa", "Mauritania" = "Africa",
"Mauritius" = "Africa", "Morocco" = "Africa", "Mozambique" = "Africa",
"Namibia" = "Africa", "Niger" = "Africa", "Nigeria" = "Africa",
"Rwanda" = "Africa", "Senegal" = "Africa", "Sierra Leone" = "Africa",
"Somalia" = "Africa", "South Africa" = "Africa", "South Sudan" = "Africa",
"Sudan" = "Africa", "Tanzania" = "Africa", "Togo" = "Africa",
"Tunisia" = "Africa", "Uganda" = "Africa", "Zambia" = "Africa",
"Zimbabwe" = "Africa",
"Australia" = "Oceania", "Fiji" = "Oceania", "Kiribati" = "Oceania",
"Marshall Islands" = "Oceania", "Micronesia, Fed. Sts." = "Oceania",
"New Zealand" = "Oceania", "Palau" = "Oceania", "Samoa" = "Oceania",
"Solomon Islands" = "Oceania", "Tonga" = "Oceania", "Vanuatu" = "Oceania"
)
data %>%
mutate(Continente = ifelse(Pais %in% names(continentes_map),
continentes_map[Pais], NA))
}
# Preparar datos - SOLO VARIABLES DE SALUD
datos_ev_mi <- Base_2022 %>%
asignar_continentes() %>%
filter(!is.na(`Esperanza vida`) &
!is.na(`Mortalidad infantil`) &
!is.na(`Gasto salud`) &
!is.na(Continente)) %>%
select(Pais, Continente, `Esperanza vida`, `Mortalidad infantil`, `Gasto salud`) %>%
mutate(
tooltip = paste0(
"<b style='font-size:14px; color:#00e5ff;'>", Pais, "</b><br>",
"<span style='color:#a259ff; font-size:11px;'>", Continente, "</span><br><br>",
"<b style='color:#e0e6ed; font-size:11px;'>INDICADORES DE SALUD:</b><br>",
"├─ Esperanza de vida: <b style='color:#00e676;'>",
round(`Esperanza vida`, 1), " años</b><br>",
"├─ Mortalidad infantil: <b style='color:#ff1744;'>",
round(`Mortalidad infantil`, 1), "/1,000</b><br>",
"└─ Gasto en salud: <b style='color:#ffd600;'>",
round(`Gasto salud`, 2), "% PIB</b>"
)
)
# Crear gráfico scatter optimizado al máximo
p <- plot_ly(
data = datos_ev_mi,
x = ~`Esperanza vida`,
y = ~`Mortalidad infantil`,
color = ~Continente,
colors = c(
"Americas" = "green",
"Europe" = "#0084ff",
"Asia" = "#ffd600",
"Africa" = "#ff1744",
"Oceania" = "#a259ff"
),
type = 'scatter',
mode = 'markers',
customdata = ~tooltip,
hovertemplate = "%{customdata}<extra></extra>",
marker = list(
size = 14, # Marcadores aún más grandes
opacity = 0.9,
line = list(color = '#ffffff', width = 2)
),
showlegend = TRUE
) %>%
layout(
title = list(
text = "<b style='color:#00e5ff; font-size:24px;'>Salud Poblacional: Esperanza de Vida vs Mortalidad Infantil</b><br>
<span style='color:#8b92a0; font-size:14px;'>Año 2022 | Relación inversa: mejor salud = mayor EV y menor MI</span>",
x = 0.5,
xanchor = 'center',
y = 0.95
),
xaxis = list(
title = "<b style='font-size:16px;'>Esperanza de vida al nacer (años)</b>",
gridcolor = '#12161f',
showgrid = TRUE,
zeroline = FALSE,
range = c(40, 90), # Rango más amplio
tickfont = list(color = '#8b92a0', size = 13),
titlefont = list(color = '#e0e6ed', size = 16)
),
yaxis = list(
title = "<b style='font-size:16px;'>Mortalidad infantil (por 1,000 nacidos vivos)</b>",
gridcolor = '#12161f',
showgrid = TRUE,
zeroline = FALSE,
range = c(0, 110),
tickfont = list(color = '#8b92a0', size = 13),
titlefont = list(color = '#e0e6ed', size = 16)
),
plot_bgcolor = '#000000',
paper_bgcolor = '#0a0e1a',
font = list(family = "Arial, sans-serif", color = '#e0e6ed', size = 13),
legend = list(
title = list(text = "<b style='font-size:14px;'>Continente</b>", font = list(size = 14, color = "#00e5ff")),
bgcolor = 'rgba(10,14,26,0.95)',
bordercolor = '#00e5ff',
borderwidth = 2,
x = 0.99, # Más pegado al borde derecho
y = 0.99, # Más pegado al borde superior
xanchor = "right",
yanchor = "top",
font = list(size = 13, color = "#e0e6ed")
),
# MÁRGENES MUY COMPACTOS
margin = list(l = 80, r = 120, b = 60, t = 100), # Margen derecho reducido
hovermode = 'closest',
# ZONAS DE INTERPRETACIÓN MÁS VISIBLES
shapes = list(
# Zona ÓPTIMA
list(
type = "rect",
x0 = 75, x1 = 90,
y0 = 0, y1 = 15,
xref = "x", yref = "y",
fillcolor = "rgba(0, 230, 118, 0.15)",
line = list(color = "rgba(0, 230, 118, 0.7)", width = 2.5, dash = "dot"),
layer = "below"
),
# Zona CRÍTICA
list(
type = "rect",
x0 = 40, x1 = 65,
y0 = 40, y1 = 110,
xref = "x", yref = "y",
fillcolor = "rgba(255, 23, 68, 0.15)",
line = list(color = "rgba(255, 23, 68, 0.7)", width = 2.5, dash = "dot"),
layer = "below"
)
),
annotations = list(
# Anotación ZONA ÓPTIMA
list(
x = 82.5,
y = 25, # Mover más arriba para evitar superposición
text = "<b style='color:#00e676; font-size:13px;'>✓ ZONA ÓPTIMA</b><br><span style='color:#00e676; font-size:11px;'>Alta EV + Baja MI</span>",
showarrow = FALSE,
bgcolor = "rgba(0, 230, 118, 0.25)",
bordercolor = "#00e676",
borderwidth = 2,
borderpad = 8,
font = list(size = 11),
xanchor = "center"
),
# Anotación ZONA CRÍTICA
list(
x = 52.5,
y = 95, # Mover más abajo para evitar superposición
text = "<b style='color:#ff1744; font-size:13px;'>⚠ ZONA CRÍTICA</b><br><span style='color:#ff1744; font-size:11px;'>Baja EV + Alta MI</span>",
showarrow = FALSE,
bgcolor = "rgba(255, 23, 68, 0.25)",
bordercolor = "#ff1744",
borderwidth = 2,
borderpad = 8,
font = list(size = 11),
xanchor = "center"
),
# Anotación explicativa
list(
x = 0.02,
y = -0.12,
text = "<span style='color:#8b92a0; font-size:11px;'>Cada punto representa un país | Arrastra para zoom | Doble click para resetear</span>",
showarrow = FALSE,
xref = "paper",
yref = "paper",
xanchor = "left"
),
# Anotación de correlación (valor añadido)
list(
x = 0.98,
y = -0.12,
text = "<span style='color:#8b92a0; font-size:11px;'>Correlación inversa fuerte: r = ~ -0.85</span>",
showarrow = FALSE,
xref = "paper",
yref = "paper",
xanchor = "right"
)
)
) %>%
config(
responsive = TRUE,
displayModeBar = TRUE,
displaylogo = FALSE,
modeBarButtonsToRemove = list('lasso2d', 'select2d'),
toImageButtonOptions = list(
format = "png",
filename = "salud_poblacional_2022",
width = 1800, # Mayor resolución
height = 1000
)
)
pdatos_scatter_gg <- Base_2022 %>%
asignar_continentes() %>%
filter(
!is.na(`Acceso electricidad`) &
!is.na(`Uso internet`) &
!is.na(`Suscripciones movil`) &
!is.na(Continente) &
Continente != "Otros"
) %>%
mutate(
Electricidad = `Acceso electricidad`,
Internet = `Uso internet`,
Movil = `Suscripciones movil`,
Continente = factor(Continente,
levels = c("Africa", "Americas", "Asia", "Europe", "Oceania"))
) %>%
arrange(Continente)
p_gg <- ggplot(datos_scatter_gg, aes(x = Electricidad, y = Internet)) +
geom_abline(
intercept = 0,
slope = 1,
linetype = "dashed",
color = "#00e5ff",
linewidth = 1,
alpha = 0.3
) +
geom_point(
aes(
fill = Continente,
size = Movil,
text = paste0(
"<b style='font-size:14px;'>", Pais, "</b><br>",
"<span style='color:#a259ff; font-size:11px;'>", Continente, "</span><br><br>",
"<b style='color:#ffd600;'> INDICADORES</b><br>",
"├─ 🔌 Electricidad: <b style='color:#00e676;'>",
round(Electricidad, 1), "%</b><br>",
"├─ 🌐 Internet: <b style='color:#00e5ff;'>",
round(Internet, 1), "%</b><br>",
"└─ 📱 Móviles: <b style='color:#ffd600;'>",
round(Movil, 1), "/100 hab.</b>"
)
),
alpha = 0.78,
shape = 19,
color = NA
) +
scale_size_continuous(
name = "Suscripciones Móviles\n(por 100 hab.)",
range = c(2, 10),
breaks = c(20, 50, 100, 150),
labels = c("20", "50", "100", "150+")
) +
geom_text_repel(
aes(label = Pais),
size = 2.8,
color = "#e0e6ed",
max.overlaps = 20,
segment.color = "#00e5ff",
segment.alpha = 0.3,
segment.size = 0.3
) +
facet_wrap(~Continente, ncol = 3) +
scale_fill_manual(
name = "Continente",
values = c(
"Africa" = "#ff1744",
"Americas" = "#00e676",
"Asia" = "#ffd600",
"Europe" = "#0084ff",
"Oceania" = "#a259ff"
)
) +
scale_x_continuous(limits = c(0, 105), breaks = seq(0, 100, 20)) +
scale_y_continuous(limits = c(0, 105), breaks = seq(0, 100, 20)) +
labs(
title = "Infraestructura Digital: Análisis Multidimensional por Región",
subtitle = "Año 2022 | Tamaño de burbuja = Suscripciones Móviles (por 100 hab)",
x = "Acceso a Electricidad (% población)",
y = "Uso de Internet (% población)"
) +
theme_minimal(base_size = 11) +
theme(
plot.background = element_rect(fill = "#000000", color = NA),
panel.background = element_rect(fill = "#0a0e1a", color = NA),
panel.grid.major = element_line(color = "#12161f", linewidth = 0.3),
panel.grid.minor = element_line(color = "#12161f", linewidth = 0.2),
plot.title = element_text(
color = "#00e5ff",
face = "bold",
size = 16,
hjust = 0.5,
margin = margin(b = 8)
),
plot.subtitle = element_text(
color = "#8b92a0",
size = 11,
hjust = 0.5,
margin = margin(b = 15),
lineheight = 1.2,
face = "italic"
),
axis.title = element_text(
color = "#e0e6ed",
face = "bold",
size = 11
),
axis.text = element_text(color = "#8b92a0", size = 10),
axis.line = element_line(color = "#00e5ff", linewidth = 0.4),
strip.text = element_text(
color = "#00e5ff",
face = "bold",
size = 12,
margin = margin(b = 8)
),
strip.background = element_rect(
fill = "#1a1a3e",
color = "#00e5ff",
linewidth = 1.2
),
# LEYENDAS - AMBAS ACTIVAS
legend.background = element_rect(
fill = "#0a0e1a",
color = "#00e5ff",
linewidth = 1.2
),
legend.text = element_text(color = "#e0e6ed", size = 11),
legend.title = element_text(color = "#00e5ff", face = "bold", size = 12),
legend.key = element_rect(fill = "#0a0e1a", color = NA),
legend.key.size = unit(0.8, "cm"),
legend.position = "right",
legend.box = "vertical",
legend.spacing.y = unit(0.5, "cm"),
legend.margin = margin(10, 10, 10, 10),
plot.margin = margin(15, 15, 15, 15)
)
# Convertir a plotly y AJUSTAR LEYENDAS SEPARADAMENTE
plotly_plot <- ggplotly(p_gg, tooltip = "text") %>%
layout(
# Leyenda de continentes (arriba)
legend = list(
title = list(text = "<b>Continente</b>"),
font = list(color = "#e0e6ed", size = 11),
bgcolor = "rgba(10, 14, 26, 0.9)",
bordercolor = "#00e5ff",
borderwidth = 1,
x = 1.05,
y = 0.8,
traceorder = "normal"
),
# Leyenda de tamaño (abajo) - CREAR MANUALMENTE
annotations = list(
# Título de leyenda de tamaño
list(
x = 1.05,
y = 0.45,
xref = "paper",
yref = "paper",
text = "<b style='color:#00e5ff; font-size:12px;'>Suscripciones Móviles</b>",
showarrow = FALSE,
xanchor = "left",
yanchor = "middle",
font = list(size = 12, color = "#00e5ff")
),
# Círculo pequeño
list(
x = 1.02,
y = 0.4,
xref = "paper",
yref = "paper",
text = "●",
showarrow = FALSE,
xanchor = "center",
yanchor = "middle",
font = list(size = 15, color = "#8b92a0")
),
# Texto pequeño
list(
x = 1.08,
y = 0.4,
xref = "paper",
yref = "paper",
text = "20",
showarrow = FALSE,
xanchor = "left",
yanchor = "middle",
font = list(size = 10, color = "#e0e6ed")
),
# Círculo mediano
list(
x = 1.02,
y = 0.35,
xref = "paper",
yref = "paper",
text = "●",
showarrow = FALSE,
xanchor = "center",
yanchor = "middle",
font = list(size = 20, color = "#8b92a0")
),
# Texto mediano
list(
x = 1.08,
y = 0.35,
xref = "paper",
yref = "paper",
text = "50",
showarrow = FALSE,
xanchor = "left",
yanchor = "middle",
font = list(size = 10, color = "#e0e6ed")
),
# Círculo grande
list(
x = 1.02,
y = 0.3,
xref = "paper",
yref = "paper",
text = "●",
showarrow = FALSE,
xanchor = "center",
yanchor = "middle",
font = list(size = 25, color = "#8b92a0")
),
# Texto grande
list(
x = 1.08,
y = 0.3,
xref = "paper",
yref = "paper",
text = "100",
showarrow = FALSE,
xanchor = "left",
yanchor = "middle",
font = list(size = 10, color = "#e0e6ed")
),
# Círculo muy grande
list(
x = 1.02,
y = 0.25,
xref = "paper",
yref = "paper",
text = "●",
showarrow = FALSE,
xanchor = "center",
yanchor = "middle",
font = list(size = 30, color = "#8b92a0")
),
# Texto muy grande
list(
x = 1.08,
y = 0.25,
xref = "paper",
yref = "paper",
text = "150+",
showarrow = FALSE,
xanchor = "left",
yanchor = "middle",
font = list(size = 10, color = "#e0e6ed")
),
# Nota explicativa
list(
x = 1.05,
y = 0.18,
xref = "paper",
yref = "paper",
text = "<span style='color:#8b92a0; font-size:10px;'>(por 100 habitantes)</span>",
showarrow = FALSE,
xanchor = "left",
yanchor = "middle"
)
),
hoverlabel = list(
bgcolor = "rgba(10, 14, 26, 0.95)",
bordercolor = "#00e5ff",
font = list(color = "#e0e6ed", size = 12, family = "Arial")
),
font = list(family = "Arial", color = "#e0e6ed"),
margin = list(l = 50, r = 200, b = 50, t = 100)
) %>%
config(
responsive = TRUE,
displayModeBar = TRUE,
displaylogo = FALSE,
modeBarButtonsToRemove = list('lasso2d', 'select2d'),
toImageButtonOptions = list(
format = "png",
filename = "infraestructura_digital_final",
width = 1200,
height = 800
)
)
plotly_plot <- plotly_plot %>%
style(showlegend = FALSE, traces = c(2:6)) # Ocultar leyendas de tamaño
plotly_plotasignar_continentes <- function(data) {
continentes_map <- c(
"Argentina" = "Americas", "Bahamas, The" = "Americas", "Barbados" = "Americas",
"Belize" = "Americas", "Bolivia" = "Americas", "Brazil" = "Americas",
"Canada" = "Americas", "Chile" = "Americas", "Colombia" = "Americas",
"Costa Rica" = "Americas", "Cuba" = "Americas", "Dominica" = "Americas",
"Dominican Republic" = "Americas", "Ecuador" = "Americas", "El Salvador" = "Americas",
"Grenada" = "Americas", "Guatemala" = "Americas", "Guyana" = "Americas",
"Haiti" = "Americas", "Honduras" = "Americas", "Jamaica" = "Americas",
"Mexico" = "Americas", "Nicaragua" = "Americas", "Panama" = "Americas",
"Paraguay" = "Americas", "Peru" = "Americas", "St. Kitts and Nevis" = "Americas",
"St. Lucia" = "Americas", "St. Vincent and the Grenadines" = "Americas",
"Suriname" = "Americas", "Trinidad and Tobago" = "Americas", "United States" = "Americas",
"Uruguay" = "Americas", "Venezuela, RB" = "Americas", "Antigua and Barbuda" = "Americas",
"Albania" = "Europe", "Austria" = "Europe", "Belarus" = "Europe",
"Belgium" = "Europe", "Bosnia and Herzegovina" = "Europe", "Bulgaria" = "Europe",
"Croatia" = "Europe", "Cyprus" = "Europe", "Czech Republic" = "Europe",
"Czechia" = "Europe", "Denmark" = "Europe", "Estonia" = "Europe",
"Finland" = "Europe", "France" = "Europe", "Germany" = "Europe",
"Greece" = "Europe", "Hungary" = "Europe", "Iceland" = "Europe",
"Ireland" = "Europe", "Italy" = "Europe", "Kosovo" = "Europe",
"Latvia" = "Europe", "Lithuania" = "Europe", "Luxembourg" = "Europe",
"Malta" = "Europe", "Montenegro" = "Europe", "Netherlands" = "Europe",
"North Macedonia" = "Europe", "Norway" = "Europe", "Poland" = "Europe",
"Portugal" = "Europe", "Russian Federation" = "Europe", "Serbia" = "Europe",
"Slovak Republic" = "Europe", "Slovakia" = "Europe", "Slovenia" = "Europe",
"Spain" = "Europe", "Sweden" = "Europe", "Switzerland" = "Europe",
"Turkey" = "Europe", "Turkiye" = "Europe", "Ukraine" = "Europe",
"United Kingdom" = "Europe", "Armenia" = "Europe", "Azerbaijan" = "Europe",
"Georgia" = "Europe", "Moldova" = "Europe", "Romania" = "Europe",
"San Marino" = "Europe",
"Afghanistan" = "Asia", "Bahrain" = "Asia", "Bangladesh" = "Asia",
"Bhutan" = "Asia", "Brunei Darussalam" = "Asia", "Cambodia" = "Asia",
"China" = "Asia", "Hong Kong SAR, China" = "Asia", "India" = "Asia",
"Indonesia" = "Asia", "Iran, Islamic Rep." = "Asia", "Iraq" = "Asia",
"Israel" = "Asia", "Japan" = "Asia", "Jordan" = "Asia",
"Kazakhstan" = "Asia", "Korea, Dem. People's rep." = "Asia", "Korea, Rep." = "Asia",
"Kuwait" = "Asia", "Kyrgyz Republic" = "Asia", "Lao PDR" = "Asia",
"Lebanon" = "Asia", "Macao SAR, China" = "Asia", "Malaysia" = "Asia",
"Maldives" = "Asia", "Mongolia" = "Asia", "Myanmar" = "Asia",
"Nepal" = "Asia", "Oman" = "Asia", "Pakistan" = "Asia",
"Philippines" = "Asia", "Qatar" = "Asia", "Saudi Arabia" = "Asia",
"Singapore" = "Asia", "Sri Lanka" = "Asia", "Syrian Arab Republic" = "Asia",
"Taiwan" = "Asia", "Tajikistan" = "Asia", "Thailand" = "Asia",
"Timor-Leste" = "Asia", "Turkmenistan" = "Asia", "United Arab Emirates" = "Asia",
"Uzbekistan" = "Asia", "Vietnam" = "Asia", "Viet Nam" = "Asia",
"West Bank and Gaza" = "Asia", "Yemen, Rep." = "Asia",
"Algeria" = "Africa", "Angola" = "Africa", "Benin" = "Africa",
"Botswana" = "Africa", "Burkina Faso" = "Africa", "Burundi" = "Africa",
"Cabo Verde" = "Africa", "Cameroon" = "Africa", "Central African Republic" = "Africa",
"Chad" = "Africa", "Comoros" = "Africa", "Congo, Dem. Rep." = "Africa",
"Congo, Rep." = "Africa", "Cote d'Ivoire" = "Africa", "Djibouti" = "Africa",
"Egypt, Arab Rep." = "Africa", "Equatorial Guinea" = "Africa", "Eritrea" = "Africa",
"Eswatini" = "Africa", "Ethiopia" = "Africa", "Gabon" = "Africa",
"Gambia, The" = "Africa", "Ghana" = "Africa", "Guinea" = "Africa",
"Guinea-Bissau" = "Africa", "Kenya" = "Africa", "Lesotho" = "Africa",
"Liberia" = "Africa", "Libya" = "Africa", "Madagascar" = "Africa",
"Malawi" = "Africa", "Mali" = "Africa", "Mauritania" = "Africa",
"Mauritius" = "Africa", "Morocco" = "Africa", "Mozambique" = "Africa",
"Namibia" = "Africa", "Niger" = "Africa", "Nigeria" = "Africa",
"Rwanda" = "Africa", "Senegal" = "Africa", "Sierra Leone" = "Africa",
"Somalia" = "Africa", "South Africa" = "Africa", "South Sudan" = "Africa",
"Sudan" = "Africa", "Tanzania" = "Africa", "Togo" = "Africa",
"Tunisia" = "Africa", "Uganda" = "Africa", "Zambia" = "Africa",
"Zimbabwe" = "Africa",
"Australia" = "Oceania", "Fiji" = "Oceania", "Kiribati" = "Oceania",
"Marshall Islands" = "Oceania", "Micronesia, Fed. Sts." = "Oceania",
"New Zealand" = "Oceania", "Palau" = "Oceania", "Samoa" = "Oceania",
"Solomon Islands" = "Oceania", "Tonga" = "Oceania", "Vanuatu" = "Oceania"
)
data %>%
mutate(Continente = ifelse(Pais %in% names(continentes_map),
continentes_map[Pais], NA))
}
datos_ambiental <- Base_2022 %>%
asignar_continentes() %>%
filter(
!is.na(`Area boscosa`) &
!is.na(`Tierra cultivable`) &
!is.na(Poblacion) &
!is.na(Continente)
) %>%
select(
Pais, Continente,
`Area boscosa`,
`Tierra cultivable`,
Poblacion
) %>%
mutate(
Tamaño = Poblacion^(1/3),
Tamaño_escalado = 10 + (Tamaño - min(Tamaño)) / (max(Tamaño) - min(Tamaño)) * 30,
# Hover con colores que contrasten sobre fondo claro
Hover = paste0(
"<b style='font-size:14px; color:#000000;'>", Pais, "</b><br>",
"<span style='color:#555555; font-size:12px;'>", Continente, "</span><br><br>",
"<b style='color:#333333; font-size:12px;'>USO DE TIERRA:</b><br>",
"├─ Área Boscosa: <b style='color:#006400;'>",
round(`Area boscosa`, 1), "%</b><br>",
"├─ Tierra Cultivable: <b style='color:#8B8000;'>",
round(`Tierra cultivable`, 1), "%</b><br>",
"├─ Balance: <b style='color:#005a9e;'>",
round(`Area boscosa` + `Tierra cultivable`, 1), "% (bosque + cultivo)</b><br>",
"└─ Población: <b style='color:#8B0000;'>",
format(round(Poblacion/1e6, 1), big.mark = ",", trim = TRUE), " M</b>"
)
)
color_map <- c(
"Africa" = "#ff1744",
"Americas" = "#00e676",
"Asia" = "#ffd600",
"Europe" = "#0084ff",
"Oceania" = "#a259ff"
)
p <- plot_ly() %>%
add_trace(
data = datos_ambiental,
x = ~`Area boscosa`,
y = ~`Tierra cultivable`,
size = ~Tamaño_escalado,
color = ~Continente,
colors = color_map,
type = "scatter",
mode = "markers",
customdata = ~Hover,
hovertemplate = "%{customdata}<extra></extra>",
marker = list(
sizeref = 0.1,
sizemin = 2.5,
opacity = 0.7,
line = list(
color = "#ffffff",
width = 1.5
)
),
showlegend = TRUE
) %>%
layout(
title = list(
text = "<b style='color:#00e5ff; font-size:24px;'>Sostenibilidad Ambiental: Uso de Tierra</b><br>
<span style='color:#8b92a0; font-size:14px;'>Año 2022 | Tamaño de burbuja = Población | Balance entre conservación y agricultura</span>",
x = 0.5,
xanchor = 'center',
y = 0.95
),
xaxis = list(
title = "<b style='font-size:16px;'>Área Boscosa (% de tierra)</b>",
gridcolor = '#12161f',
showgrid = TRUE,
zeroline = FALSE,
tickfont = list(color = '#8b92a0', size = 13),
titlefont = list(color = '#e0e6ed', size = 16),
range = c(0, 100)
),
yaxis = list(
title = "<b style='font-size:16px;'>Tierra Cultivable (% de tierra)</b>",
gridcolor = '#12161f',
showgrid = TRUE,
zeroline = FALSE,
tickfont = list(color = '#8b92a0', size = 13),
titlefont = list(color = '#e0e6ed', size = 16),
range = c(0, 70)
),
plot_bgcolor = '#000000',
paper_bgcolor = '#0a0e1a',
font = list(family = "Arial, sans-serif", color = '#e0e6ed', size = 13),
legend = list(
title = list(text = "<b style='font-size:14px;'>Continente</b>", font = list(size = 14, color = "#00e5ff")),
bgcolor = 'rgba(10,14,26,0.95)',
bordercolor = '#00e5ff',
borderwidth = 1.5,
x = 0.02,
y = 0.98,
font = list(size = 12, color = "#e0e6ed")
),
margin = list(l = 100, r = 50, b = 120, t = 120),
hovermode = 'closest',
hoverlabel = list(
bgcolor = "#ffffff",
bordercolor = "#00e5ff",
font = list(
color = "#000000",
size = 12,
family = "Arial"
),
align = "left"
),
shapes = list(
list(
type = "rect",
x0 = 60, x1 = 100,
y0 = 0, y1 = 20,
xref = "x", yref = "y",
fillcolor = "rgba(0, 230, 118, 0.1)",
line = list(color = "rgba(0, 230, 118, 0.6)", width = 2, dash = "dot"),
layer = "below"
),
list(
type = "rect",
x0 = 0, x1 = 30,
y0 = 40, y1 = 70,
xref = "x", yref = "y",
fillcolor = "rgba(255, 214, 0, 0.1)",
line = list(color = "rgba(255, 214, 0, 0.6)", width = 2, dash = "dot"),
layer = "below"
),
list(
type = "rect",
x0 = 30, x1 = 60,
y0 = 20, y1 = 40,
xref = "x", yref = "y",
fillcolor = "rgba(0, 132, 255, 0.1)",
line = list(color = "rgba(0, 132, 255, 0.6)", width = 2, dash = "dot"),
layer = "below"
),
list(
type = "rect",
x0 = 0, x1 = 30,
y0 = 0, y1 = 20,
xref = "x", yref = "y",
fillcolor = "rgba(255, 23, 68, 0.1)",
line = list(color = "rgba(255, 23, 68, 0.6)", width = 2, dash = "dot"),
layer = "below"
)
),
annotations = list(
list(
x = 82, y = 10,
text = "<b style='color:#00e676; font-size:12px;'>🌲 CONSERVACIÓN</b>",
showarrow = FALSE,
bgcolor = "rgba(0, 230, 118, 0.2)",
bordercolor = "#00e676",
borderwidth = 1.5,
borderpad = 6,
font = list(size = 11)
),
list(
x = 25, y = 65,
text = "<b style='color:#ffd600; font-size:12px;'>🌾 AGRÍCOLA</b>",
showarrow = FALSE,
bgcolor = "rgba(255, 214, 0, 0.2)",
bordercolor = "#ffd600",
borderwidth = 1.5,
borderpad = 6,
font = list(size = 11)
),
list(
x = 60, y = 40,
text = "<b style='color:#0084ff; font-size:12px;'>⚖️ BALANCE</b>",
showarrow = FALSE,
bgcolor = "rgba(0, 132, 255, 0.2)",
bordercolor = "#0084ff",
borderwidth = 1.5,
borderpad = 6,
font = list(size = 11)
),
list(
x = 15, y = 20,
text = "<b style='color:#ff1744; font-size:12px;'>⚠️ CRÍTICA</b>",
showarrow = FALSE,
bgcolor = "rgba(255, 23, 68, 0.2)",
bordercolor = "#ff1744",
borderwidth = 1.5,
borderpad = 6,
font = list(size = 10)
),
list(
x = 0.5, y = -0.15,
xref = "paper", yref = "paper",
text = "<span style='color:#8b92a0; font-size:12px;'></b> Burbujas más grandes = mayor población. Verde = alta cobertura boscosa. Amarillo = alta agricultura. Equilibrio = desarrollo sostenible.</span>",
showarrow = FALSE,
xanchor = "center",
yanchor = "top",
font = list(size = 11, color = "#8b92a0")
)
)
) %>%
config(
responsive = TRUE,
displayModeBar = TRUE,
displaylogo = FALSE,
modeBarButtonsToRemove = list('lasso2d', 'select2d'),
toImageButtonOptions = list(
format = "png",
filename = "sostenibilidad_ambiental_2022",
width = 1600,
height = 1000
)
)
pasignar_continentes <- function(data) {
continentes_map <- c(
"Argentina" = "Americas", "Bahamas, The" = "Americas", "Barbados" = "Americas",
"Belize" = "Americas", "Bolivia" = "Americas", "Brazil" = "Americas",
"Canada" = "Americas", "Chile" = "Americas", "Colombia" = "Americas",
"Costa Rica" = "Americas", "Cuba" = "Americas", "Dominica" = "Americas",
"Dominican Republic" = "Americas", "Ecuador" = "Americas", "El Salvador" = "Americas",
"Grenada" = "Americas", "Guatemala" = "Americas", "Guyana" = "Americas",
"Haiti" = "Americas", "Honduras" = "Americas", "Jamaica" = "Americas",
"Mexico" = "Americas", "Nicaragua" = "Americas", "Panama" = "Americas",
"Paraguay" = "Americas", "Peru" = "Americas", "St. Kitts and Nevis" = "Americas",
"St. Lucia" = "Americas", "St. Vincent and the Grenadines" = "Americas",
"Suriname" = "Americas", "Trinidad and Tobago" = "Americas", "United States" = "Americas",
"Uruguay" = "Americas", "Venezuela, RB" = "Americas", "Antigua and Barbuda" = "Americas",
"Albania" = "Europe", "Austria" = "Europe", "Belarus" = "Europe",
"Belgium" = "Europe", "Bosnia and Herzegovina" = "Europe", "Bulgaria" = "Europe",
"Croatia" = "Europe", "Cyprus" = "Europe", "Czech Republic" = "Europe",
"Czechia" = "Europe", "Denmark" = "Europe", "Estonia" = "Europe",
"Finland" = "Europe", "France" = "Europe", "Germany" = "Europe",
"Greece" = "Europe", "Hungary" = "Europe", "Iceland" = "Europe",
"Ireland" = "Europe", "Italy" = "Europe", "Kosovo" = "Europe",
"Latvia" = "Europe", "Lithuania" = "Europe", "Luxembourg" = "Europe",
"Malta" = "Europe", "Montenegro" = "Europe", "Netherlands" = "Europe",
"North Macedonia" = "Europe", "Norway" = "Europe", "Poland" = "Europe",
"Portugal" = "Europe", "Russian Federation" = "Europe", "Serbia" = "Europe",
"Slovak Republic" = "Europe", "Slovakia" = "Europe", "Slovenia" = "Europe",
"Spain" = "Europe", "Sweden" = "Europe", "Switzerland" = "Europe",
"Turkey" = "Europe", "Turkiye" = "Europe", "Ukraine" = "Europe",
"United Kingdom" = "Europe", "Armenia" = "Europe", "Azerbaijan" = "Europe",
"Georgia" = "Europe", "Moldova" = "Europe", "Romania" = "Europe",
"San Marino" = "Europe",
"Afghanistan" = "Asia", "Bahrain" = "Asia", "Bangladesh" = "Asia",
"Bhutan" = "Asia", "Brunei Darussalam" = "Asia", "Cambodia" = "Asia",
"China" = "Asia", "Hong Kong SAR, China" = "Asia", "India" = "Asia",
"Indonesia" = "Asia", "Iran, Islamic Rep." = "Asia", "Iraq" = "Asia",
"Israel" = "Asia", "Japan" = "Asia", "Jordan" = "Asia",
"Kazakhstan" = "Asia", "Korea, Dem. People's rep." = "Asia", "Korea, Rep." = "Asia",
"Kuwait" = "Asia", "Kyrgyz Republic" = "Asia", "Lao PDR" = "Asia",
"Lebanon" = "Asia", "Macao SAR, China" = "Asia", "Malaysia" = "Asia",
"Maldives" = "Asia", "Mongolia" = "Asia", "Myanmar" = "Asia",
"Nepal" = "Asia", "Oman" = "Asia", "Pakistan" = "Asia",
"Philippines" = "Asia", "Qatar" = "Asia", "Saudi Arabia" = "Asia",
"Singapore" = "Asia", "Sri Lanka" = "Asia", "Syrian Arab Republic" = "Asia",
"Taiwan" = "Asia", "Tajikistan" = "Asia", "Thailand" = "Asia",
"Timor-Leste" = "Asia", "Turkmenistan" = "Asia", "United Arab Emirates" = "Asia",
"Uzbekistan" = "Asia", "Vietnam" = "Asia", "Viet Nam" = "Asia",
"West Bank and Gaza" = "Asia", "Yemen, Rep." = "Asia",
"Algeria" = "Africa", "Angola" = "Africa", "Benin" = "Africa",
"Botswana" = "Africa", "Burkina Faso" = "Africa", "Burundi" = "Africa",
"Cabo Verde" = "Africa", "Cameroon" = "Africa", "Central African Republic" = "Africa",
"Chad" = "Africa", "Comoros" = "Africa", "Congo, Dem. Rep." = "Africa",
"Congo, Rep." = "Africa", "Cote d'Ivoire" = "Africa", "Djibouti" = "Africa",
"Egypt, Arab Rep." = "Africa", "Equatorial Guinea" = "Africa", "Eritrea" = "Africa",
"Eswatini" = "Africa", "Ethiopia" = "Africa", "Gabon" = "Africa",
"Gambia, The" = "Africa", "Ghana" = "Africa", "Guinea" = "Africa",
"Guinea-Bissau" = "Africa", "Kenya" = "Africa", "Lesotho" = "Africa",
"Liberia" = "Africa", "Libya" = "Africa", "Madagascar" = "Africa",
"Malawi" = "Africa", "Mali" = "Africa", "Mauritania" = "Africa",
"Mauritius" = "Africa", "Morocco" = "Africa", "Mozambique" = "Africa",
"Namibia" = "Africa", "Niger" = "Africa", "Nigeria" = "Africa",
"Rwanda" = "Africa", "Senegal" = "Africa", "Sierra Leone" = "Africa",
"Somalia" = "Africa", "South Africa" = "Africa", "South Sudan" = "Africa",
"Sudan" = "Africa", "Tanzania" = "Africa", "Togo" = "Africa",
"Tunisia" = "Africa", "Uganda" = "Africa", "Zambia" = "Africa",
"Zimbabwe" = "Africa",
"Australia" = "Oceania", "Fiji" = "Oceania", "Kiribati" = "Oceania",
"Marshall Islands" = "Oceania", "Micronesia, Fed. Sts." = "Oceania",
"New Zealand" = "Oceania", "Palau" = "Oceania", "Samoa" = "Oceania",
"Solomon Islands" = "Oceania", "Tonga" = "Oceania", "Vanuatu" = "Oceania"
)
data %>%
mutate(Continente = ifelse(Pais %in% names(continentes_map),
continentes_map[Pais], NA))
}
datos_riesgos <- Base_2022 %>%
asignar_continentes() %>%
filter(
!is.na(`Crecimiento poblacion`) &
!is.na(Poblacion) &
!is.na(Continente) &
Poblacion > 0
) %>%
select(
Pais, Continente,
Poblacion,
`Crecimiento poblacion`,
`Mortalidad infantil`,
`Esperanza vida`,
PIB_per
) %>%
arrange(desc(Poblacion)) %>%
slice_head(n = 60) %>%
mutate(
Poblacion_millones = Poblacion / 1e6,
# Clasificación simplificada
Clasificacion = case_when(
`Crecimiento poblacion` > 2 ~ "Dividendo Demográfico",
`Crecimiento poblacion` >= 0.5 & `Crecimiento poblacion` <= 2 ~ "Madurez Estable",
`Crecimiento poblacion` < 0.5 ~ "Declive Poblacional",
TRUE ~ "Sin Clasificar"
),
tooltip = paste0(
"<b style='font-size:14px; color:#00e5ff;'>", Pais, "</b><br>",
"<span style='color:#a259ff; font-size:12px;'>", Continente, "</span><br><br>",
"<b style='color:#e0e6ed; font-size:12px;'>INDICADORES DEMOGRÁFICOS:</b><br>",
"├─ Población: <b style='color:#ffd600;'>",
format(round(Poblacion_millones, 1), big.mark = ",", decimal.mark = ".", trim = TRUE), " M</b><br>",
"├─ Crecimiento: <b style='color:#00e676;'>",
round(`Crecimiento poblacion`, 2), "%</b><br>",
"├─ Esperanza Vida: <b style='color:#00e5ff;'>",
round(`Esperanza vida`, 1), " años</b><br>",
"├─ Mortalidad Infantil: <b style='color:#ff1744;'>",
round(`Mortalidad infantil`, 1), "/1000</b><br>",
"└─ PIB per cápita: <b style='color:#a259ff;'>$",
format(round(PIB_per), big.mark = ","), "</b><br>",
"<br><b>Clasificación:</b> <span style='color:#00e676;'>", Clasificacion, "</span>"
)
)
fig_treemap <- plot_ly(
data = datos_riesgos,
type = "treemap",
labels = ~Pais,
parents = ~"",
values = ~Poblacion,
branchvalues = "total",
marker = list(
colors = ~`Crecimiento poblacion`,
colorscale = list(
c(0, "#ff1744"),
c(0.3, "#ff6b00"),
c(0.5, "#fdd835"),
c(0.7, "#76ff03"),
c(1, "#00e676")
),
cmin = -2,
cmax = 4,
showscale = TRUE,
colorbar = list(
title = list(
text = "<b>Crecimiento<br>Anual (%)</b>",
font = list(size = 12, color = "#e0e6ed")
),
tickvals = c(-2, -1, 0, 1, 2, 3, 4),
ticktext = c("-2%", "-1%", "0%", "1%", "2%", "3%", "4%"),
thickness = 20,
len = 0.8,
x = 1.05, # Posición ajustada
y = 0.5,
tickfont = list(size = 11, color = "#8b92a0")
),
line = list(color = "#0a0e1a", width = 2),
opacity = 0.9
),
textinfo = "label+value",
texttemplate = "<b>%{label}</b><br>%{value:.0f}M",
textposition = "middle center",
textfont = list(
size = 14,
color = "white",
family = "Arial"
),
customdata = ~tooltip,
hovertemplate = "%{customdata}<extra></extra>",
showlegend = FALSE
)
fig_treemap <- fig_treemap %>%
layout(
title = list(
text = "<b style='color:#00e5ff; font-size:24px;'>Oportunidades y Riesgos Demográficos Globales</b><br>
<span style='color:#8b92a0; font-size:14px;'>Top 60 países | Tamaño = Población | Color = Crecimiento Anual (2022)</span>",
x = 0.5,
xanchor = 'center',
y = 0.95
),
plot_bgcolor = '#000000',
paper_bgcolor = '#0a0e1a',
font = list(family = "Arial, sans-serif", color = '#e0e6ed', size = 12),
margin = list(l = 10, r = 150, b = 100, t = 120),
annotations = list(
list(
x = 0.5,
y = -0.08,
xref = "paper",
yref = "paper",
text = "<span style='color:#e0e6ed; font-size:12px;'><b>📊 LECTURA:</b>
<span style='color:#00e676;'>Verde (alto crecimiento) = Oportunidades demográficas</span> |
<span style='color:#ff1744;'>Rojo (bajo/negativo) = Riesgos de declive</span> |
<span style='color:#fdd835;'>Amarillo = Transición estable</span></span>",
showarrow = FALSE,
xanchor = "center",
align = "center"
)
)
) %>%
config(
responsive = TRUE,
displayModeBar = TRUE,
displaylogo = FALSE,
modeBarButtonsToRemove = list('lasso2d', 'select2d'),
toImageButtonOptions = list(
format = "png",
filename = "oportunidades_riesgos_demograficos",
width = 1600,
height = 1000
)
)
fig_treemapvariables_mapa <- list(
"Crecimiento PIB" = "Crecimiento PIB",
"Acceso electricidad" = "Acceso electricidad",
"Crecimiento poblacion" = "Crecimiento poblacion"
)
world <- ne_countries(scale = "medium", returnclass = "sf")
mapeo_paises <- c(
"United States of America" = "United States",
"Russia" = "Russian Federation",
"South Korea" = "Korea, Rep.",
"North Korea" = "Korea, Dem. People's Rep.",
"Egypt" = "Egypt, Arab Rep.",
"Democratic Republic of the Congo" = "Congo, Dem. Rep.",
"Republic of the Congo" = "Congo, Rep.",
"Laos" = "Lao PDR",
"Syria" = "Syrian Arab Republic",
"Venezuela" = "Venezuela, RB",
"Iran" = "Iran, Islamic Rep.",
"Czech Republic" = "Czechia",
"Slovakia" = "Slovak Republic",
"Kyrgyzstan" = "Kyrgyz Republic",
"Yemen" = "Yemen, Rep.",
"Turkey" = "Turkiye",
"Gambia" = "Gambia, The",
"Bahamas" = "Bahamas, The",
"Ivory Coast" = "Cote d'Ivoire",
"Brunei" = "Brunei Darussalam",
"Cape Verde" = "Cabo Verde",
"Hong Kong" = "Hong Kong SAR, China",
"Macao" = "Macao SAR, China",
"Macedonia" = "North Macedonia",
"Saint Lucia" = "St. Lucia",
"Saint Vincent and the Grenadines" = "St. Vincent and the Grenadines",
"Saint Kitts and Nevis" = "St. Kitts and Nevis",
"Myanmar" = "Myanmar",
"Bolivia" = "Bolivia",
"Libya" = "Libya",
"Tanzania" = "Tanzania",
"Eswatini" = "Eswatini",
"Timor-Leste" = "Timor-Leste"
)
mapeo_df <- data.frame(
name_world = names(mapeo_paises),
name_data = unname(mapeo_paises),
stringsAsFactors = FALSE
)
world_data <- world %>%
left_join(mapeo_df, by = c("name" = "name_world")) %>%
left_join(
Base_2022 %>% select(Pais, all_of(unlist(variables_mapa))),
by = c("name_data" = "Pais")
) %>%
mutate(
across(
all_of(unlist(variables_mapa)),
~ifelse(is.na(.) & name %in% Base_2022$Pais,
Base_2022[[cur_column()]][match(name, Base_2022$Pais)], .)
)
)paletas <- list(
"Crecimiento PIB" = colorNumeric(
palette = colorRampPalette(c("#ff1744", "#ff6b00", "#ffd600", "#00e676", "#00e5ff"))(100),
domain = world_data$`Crecimiento PIB`,
na.color = "#1a1a2e"
),
"Acceso electricidad" = colorNumeric(
palette = colorRampPalette(c("#1a1a2e", "#0084ff", "#00e5ff", "#00e676", "#ffd600"))(100),
domain = world_data$`Acceso electricidad`,
na.color = "#1a1a2e"
),
"Crecimiento poblacion" = colorNumeric(
palette = colorRampPalette(c("#0084ff", "#00e5ff", "#a259ff", "#ff6b00", "#ff1744"))(100),
domain = world_data$`Crecimiento poblacion`, # ✅ CORREGIDO
na.color = "#1a1a2e"
)
)
mapa <- leaflet(world_data,
width = "100%",
height = "550px",
options = leafletOptions(
minZoom = 2,
maxZoom = 7,
worldCopyJump = TRUE
)) %>%
setView(lng = 15, lat = 20, zoom = 2.2) %>%
addProviderTiles("CartoDB.DarkMatter")
for (var_display in names(variables_mapa)) {
var_col <- variables_mapa[[var_display]]
pal <- paletas[[var_display]]
unidad <- if(grepl("Crecimiento", var_display)) "%" else "%"
labels <- sprintf(
"<div style='font-family: sans-serif;'>
<strong style='color: #00e5ff; font-size: 15px;'>%s</strong><br/>
<span style='color: #8b92a0; font-size: 12px;'>%s:</span><br/>
<strong style='color: #00e5ff; font-size: 14px;'>%s</strong>
</div>",
world_data$name,
var_display,
ifelse(is.na(world_data[[var_col]]),
"Sin datos",
paste0(round(world_data[[var_col]], 2), unidad))
) %>% lapply(HTML)
mapa <- mapa %>%
addPolygons(
fillColor = ~pal(world_data[[var_col]]),
weight = 1.2,
opacity = 0.9,
color = "#00e5ff",
fillOpacity = 0.75,
highlight = highlightOptions(
weight = 2.5,
color = "#00ffff",
fillOpacity = 0.9,
bringToFront = TRUE
),
label = labels,
labelOptions = labelOptions(
style = list(
"background" = "rgba(10, 14, 26, 0.95)",
"border" = "2px solid #00e5ff",
"border-radius" = "6px",
"padding" = "10px",
"box-shadow" = "0 0 15px rgba(0, 229, 255, 0.6)"
),
textsize = "13px"
),
group = var_display
)
}
mapa <- mapa %>%
addLayersControl(
baseGroups = names(variables_mapa),
options = layersControlOptions(collapsed = FALSE),
position = "topleft"
) %>%
hideGroup(names(variables_mapa)[-1])
mapa <- mapa %>%
htmlwidgets::onRender("
function(el, x) {
var map = this;
// Configuración de leyendas
var legendConfigs = {
'Crecimiento PIB': {
title: 'CRECIMIENTO DEL PIB',
subtitle: '(% anual)',
min: -10,
max: 10,
colors: ['#ff1744', '#ff6b00', '#ffd600', '#00e676', '#00e5ff'],
labels: ['-10%', '-5%', '0%', '5%', '10%']
},
'Acceso electricidad': {
title: 'ACCESO A ELECTRICIDAD',
subtitle: '(% de población)',
min: 0,
max: 100,
colors: ['#1a1a2e', '#0084ff', '#00e5ff', '#00e676', '#ffd600'],
labels: ['0%', '25%', '50%', '75%', '100%']
},
'Crecimiento poblacion': {
title: 'CRECIMIENTO POBLACIÓN',
subtitle: '(% anual)',
min: -2,
max: 4,
colors: ['#0084ff', '#00e5ff', '#a259ff', '#ff6b00', '#ff1744'],
labels: ['-2%', '-1%', '0%', '2%', '4%']
}
};
// Crear leyenda
var LegendControl = L.Control.extend({
options: { position: 'bottomright' },
onAdd: function(map) {
var div = L.DomUtil.create('div', 'info legend');
div.id = 'bar-legend';
return div;
}
});
map.addControl(new LegendControl());
// Función para crear barra de gradiente
function updateLegend(varName) {
var div = document.getElementById('bar-legend');
var config = legendConfigs[varName];
// Crear gradiente CSS
var gradient = 'linear-gradient(to right';
config.colors.forEach(function(color) {
gradient += ', ' + color;
});
gradient += ')';
var html = '<div style=\"background: linear-gradient(135deg, #0a0e1a, #12161f); padding: 18px; border-radius: 10px; border: 2px solid #00e5ff; box-shadow: 0 8px 32px rgba(0,0,0,0.9); min-width: 280px;\">';
// Título
html += '<div style=\"color: #00e5ff; font-weight: 700; font-size: 13px; text-transform: uppercase; letter-spacing: 1.2px; margin-bottom: 4px; text-align: center; text-shadow: 0 0 10px rgba(0,229,255,0.5);\">' + config.title + '</div>';
html += '<div style=\"color: #8b92a0; font-size: 11px; text-align: center; margin-bottom: 12px;\">' + config.subtitle + '</div>';
// Barra de color
html += '<div style=\"height: 20px; background: ' + gradient + '; border-radius: 4px; border: 1px solid #00e5ff; margin-bottom: 8px; box-shadow: inset 0 0 10px rgba(0,0,0,0.5);\"></div>';
// Etiquetas
html += '<div style=\"display: flex; justify-content: space-between; font-size: 11px; color: #e0e6ed;\">';
config.labels.forEach(function(label) {
html += '<span>' + label + '</span>';
});
html += '</div>';
html += '</div>';
div.innerHTML = html;
}
// Inicializar
updateLegend('Crecimiento PIB');
// Actualizar al cambiar capa
map.on('baselayerchange', function(e) {
updateLegend(e.name);
});
// Estilizar control de capas
setTimeout(function() {
var ctrl = document.querySelector('.leaflet-control-layers');
if (ctrl) {
ctrl.style.background = 'linear-gradient(135deg, #0a0e1a, #12161f)';
ctrl.style.border = '2px solid rgba(0, 229, 255, 0.4)';
ctrl.style.borderRadius = '10px';
ctrl.style.padding = '18px';
ctrl.style.boxShadow = '0 8px 32px rgba(0, 0, 0, 0.9)';
}
var base = document.querySelector('.leaflet-control-layers-base');
if (base && !document.getElementById('sel-title')) {
var title = document.createElement('div');
title.id = 'sel-title';
title.innerHTML = '<strong style=\"color: #00e5ff; font-size: 13px; text-transform: uppercase; letter-spacing: 1.5px; text-shadow: 0 0 10px rgba(0,229,255,0.5);\">📊 SELECCIONA VARIABLE</strong>';
title.style.marginBottom = '12px';
title.style.paddingBottom = '10px';
title.style.borderBottom = '2px solid rgba(0, 229, 255, 0.3)';
base.insertBefore(title, base.firstChild);
}
var labels = document.querySelectorAll('.leaflet-control-layers-base label');
labels.forEach(function(label, idx) {
label.style.color = '#e0e6ed';
label.style.fontSize = '13px';
label.style.fontWeight = '600';
label.style.padding = '9px 12px';
label.style.margin = '4px 0';
label.style.display = 'block';
label.style.borderRadius = '6px';
label.style.cursor = 'pointer';
label.style.transition = 'all 0.3s';
var input = label.querySelector('input');
if (input) {
input.style.accentColor = '#00e5ff';
if (idx === 0) {
label.style.background = 'rgba(0, 229, 255, 0.15)';
label.style.color = '#00e5ff';
}
}
label.addEventListener('mouseenter', function() {
this.style.background = 'rgba(0, 229, 255, 0.1)';
this.style.color = '#00e5ff';
});
label.addEventListener('mouseleave', function() {
if (!this.querySelector('input').checked) {
this.style.background = 'transparent';
this.style.color = '#e0e6ed';
}
});
});
var inputs = document.querySelectorAll('.leaflet-control-layers-base input');
inputs.forEach(function(input) {
input.addEventListener('change', function() {
labels.forEach(function(l) {
l.style.background = 'transparent';
l.style.color = '#e0e6ed';
});
if (this.checked) {
this.parentElement.style.background = 'rgba(0, 229, 255, 0.15)';
this.parentElement.style.color = '#00e5ff';
}
});
});
}, 100);
}
")
mapa